“prefer duplication over the wrong abstraction”
- Programmer A sees duplication.
- Programmer A extracts duplication and gives it a name.This creates a new abstraction. It could be a new method, or perhaps even a new class.
Programmer A replaces the duplication with the new abstraction.
Ah, the code is perfect. Programmer A trots happily away.
- Time passes.
A new requirement appears for which the current abstraction is almost perfect.
- Programmer B gets tasked to implement this requirement.Programmer B feels honor-bound to retain the existing abstraction, but since isn’t exactly the same for every case, they alter the code to take a parameter, and then add logic to conditionally do the right thing based on the value of that parameter.
What was once a universal abstraction now behaves differently for different cases.
- Another new requirement arrives.
Another additional parameter.
Another new conditional.
Loop until code becomes incomprehensible.
- You appear in the story about here, and your life takes a dramatic turn for the worse.
I totally agree. In most cases it’s a good rule of thumb.
– Return as soon as you know your method cannot do any more meaningful work
– Reduce indentation by using if/return instead of a top-level if/else
– Try keep the “meat” of your method at the lowest indentation level.
– Error handling is noise.
The development of the user interface for a large commercial software product like Microsoft® Windows 95 involves many people, broad design goals, and an aggressive work schedule. This design briefing describes how the usability engineering principles of iterative design and problem tracking were successfully applied to make the development of the UI more manageable. Specific design problems and their solutions are also discussed.
Iterative design, Microsoft Windows, problem tracking, rapid prototyping, usability engineering, usability testing.
However, the fixes would not have been made if the team had not believed in making the most-usable product possible. Key to this belief was our understanding that we probably weren’t going to get it right the first time and that not getting it right was as useful and interesting to creating a product as getting it right was.
Highlights from https://www.simplethread.com/software-complexity-killing-us/.
We get enthralled by the maelstrom of complexity and the mental puzzle of engineering elegant solutions: Another layer of abstraction! DRY it up! Separate the concerns! Composition over inheritance! This too is understandable, but in the process, we often lose sight of the business problems being solved and forget that managing complexity is the second most important responsibility of software developers.
Looking forward to the future, it is unlikely that language design will give us the same kinds of improvements we have seen over the last few decades.
We, as an industry, need to find ways to simplify the process of building software, without ignoring the legitimate complexities of businesses. We need to admit that not every application out there needs the same level of interface sophistication and operational scalability as Gmail.
Our answer to the growing complexity of doing business cannot be adding complexity to the development process – no matter how elegant it may seem.
We must find ways to manage complexity by simplifying the development process. Because even though managing complexity is our second most important responsibility, we must always remember the most important responsibility of software developers: delivering value through working software.
Collaboration: Helping others is a priority, even when it is not related to the goals that you are trying to achieve. You are expected to ask others for help and advice. Anyone can chime in on any subject, including people who don’t work at GitLab. The person who has to do the work decides how to do it but you should always take the suggestions seriously and try to respond and explain.
- Kindness: We don’t want jerks in our team. Some companies say Evaluate People Accurately, Not “Kindly”. We’re all for accurate assessment but we think it must be done in a kind way. Give as much positive feedback as you can and do it in a public way.
- Negative is 1-1: Give negative feedback in the smallest setting possible, one-on-one video calls are preferred.
- Say thanks: Recognize the people that helped you publicly, for example in our #thanks chat channel.
- Feedback is always about the work: Clearly make negative feedback about the work itself, not the person. When giving feedback always provide at least one clear and recent example. If a person is going through a hard time in their personal life, then take that into account. An example of giving positive feedback is our thanks chat channel.
- Get to know each other: We use a lot of text based communication and if you know the person behind the text it will be easier to prevent conflicts. So encourage people to get to know each other on a personal level through our team calls, virtual coffee breaks, and during our summit.
- Don’t pull rank: If you have to remind someone of the position you have in the company you’re doing something wrong, people already know we have a hierarchical decision making process. Explain why you’re making the decision and respect everyone irrespective of their function.
- Say sorry: If you made a mistake apologize. Saying sorry is not a sign of weakness but one of strength. The people that do the most will likely make the most mistakes.
- No ego: Don’t defend a point to win an argument or double-down on a mistake. You are not your work, you don’t have to defend your point, you have to search for the right answer together.
- See others succeed: An applicant that talked to a lot of people inside GitLab mentioned that compared to other companies one thing stood out the most. Everyone at GitLab mentioned wanting to see each other succeed.
Efficiency: We care about working on the right things, not doing more than needed, and not duplicating work. This enables us to achieve more progress which makes our work more fulfilling.
- Boring solutions: Use the most simple and boring solution for a problem. You can always make it more complex later if that is needed. The speed of innovation for our organization and product is constrained by the total complexity we have added so far, so every little reduction in complexity helps. Don’t pick an interesting technology just to make your work more fun, using code that is popular will ensure many bugs are already solved and its familiarity makes it easier for others to contribute.
- Be respectful of other’s time: Consider the time investment you are asking others to make with meetings and a permission process. Try to avoid meetings and if one is needed make attendance optional by making the invite optional, by having a clear agenda linked from the invite, and by documenting the outcome. Instead of having people ask permission trust their judgment and offer a consultation process if they have questions.
- Spend company money like it’s your own: Every dollar we spend will have to be earned back, be as frugal with company money as you are with your own.
- Freedom: You should have clear objectives and the freedom to work on them as you see fit.
- Frugality: Amazon states it best with: “Accomplish more with less. Constraints breed resourcefulness, self-sufficiency and invention. There are no extra points for growing headcount, budget size or fixed expense.”.
- ConvDev: We work according to the principles of conversational development.
- Short verbal answers: Give short answers to verbal questions so the other party has the opportunity to ask more or move on.
- Keep broadcasts short: Keep 1 to many written communication short, as mentioned in this HBR study: “A majority say that what they read is frequently ineffective because it’s too long, poorly organized, unclear, filled with jargon, and imprecise.”.
- Managers of one: We want team members to be a manager of one who doesn’t need daily check-ins to achieve their goals.
- Responsibility: Over rigidity when possible we give people the responsibility to make a decision and hold them accountable for that instead of imposing rules and approval processes.
- Accept mistakes: Not every problem should lead to a new process to prevent them. Additional process make all actions more inefficient, a mistake only affects one.
Iteration: We do the smallest thing possible and get it out as quickly as possible. If you make suggestions that can be excluded from the first iteration turn them into a separate issue that you link. Don’t write a large plan, only write the first step. Trust that you’ll know better how to proceed after something is released. You’re doing it right if you’re slightly embarrassed by the minimal feature set shipped in the first iteration. This value is the one people underestimate when they join GitLab, the impact both on your work process and on how much you achieve is greater than anticipated. In the beginning it hurts to make decisions fast and to see that things are changed with less consultation. But frequently the simplest version turns out to be the best one.
- Reduce cycle time: Short iterations reduce our cycle time.
- Work as part of the community small iteration make it easier to work with the wider community. Their work looks more like our work and our work is quicker to give feedback too.
- Minimum Viable Change (MVC): Always look to make the quickest change possible to improve the outcome. If you think it is better than what is there now do it, no need to wait for something polished.
- Make a proposal: If you need to decide something as a team make a proposal instead of calling a meeting to get everyone’s input. Having a proposal will be a much more effective use of everyone’s time. The people that receive the proposal should not feel left out, the person making it should not feel bad if a completely different proposal is implemented. Don’t let your ego to be involved early or to see your solution implemented stand in the way of getting to the best outcome.
- Everything is in draft: At GitLab we rarely put draft on any content or proposals. Everything is always in draft an subject to change.
- Under construction: As we get more users they will ask for stability, especially in our UX. We should always optimize for the long term. This means that users will be inconvenienced in the short term, but current and future users will enjoy a better product in the end.