112

Background

I am a software engineer and a TDD practitioner in my company. My manager is also responsible for coding (if needed), and managing his engineer subordinates.

I got into a few heated debates with my manager regarding the use of software design patterns recently.

The problem

Frequently when I am tasked to implement a feature and code, I am challenged by my manager during code reviews for my use of common software design patterns. He thinks it is unnecessary and one should code as ‘straightforward’ as possible. I put quotes on straightforward, because we seem to disagree what the scope of a ‘feature’ should be. In many cases, the feature is not as ‘straightforward’ as my manager thinks and require the use of design patterns to separate responsibilities and minimize impact to the (mostly untested) code base.

There are two common use cases I will apply design patterns to solve a problem:

  • Implementing new features that require changes to an untestable, legacy class

    • I solve this by applying a decorator to the original interface so that the new code I write can be easily unit tested and make sure my code integrates well with the legacy code.
    • His response is that he finds it confusing having multiple implementations of an interface and he thinks creating a new interface with another name (with the same members) is the way to go. However, this breaks the dependency inversion principle as the high-level logic is now changed to suit the low-level details.
    • I tried to reason by explaining that I am trying to minimize risk by minimizing changes to untested code, plus my design is easier to unit test and to be proven correct, but he thinks I am over-engineering stuff.
  • Tackling uncertainties by interfacing the unknowns

    • Quite often the requirements for a new feature is not thought out thoroughly. Faced with deadlines, we have to leave ‘holes’ in our code in order to let the business make up their mind without impacting progress.
    • For example, I might be implementing an interface to retrieve a runtime value from some unknown data source, which I implemented a decorator which takes an IRuntimeValueProvider to retrieve it during runtime. I can leave the actual implementation till the decision is made without impacting other business logic.
    • The manager thinks I am introducing interfaces with names he is not familiar with such as IHttpContentFactory, IHttpClientProvider. He is still not satisfied with my explanation and demonstration that these factories serve specific purposes in constructing components and provide a seam to extensibility.
      • In the debate of my usage of IHttpClientFactory to abstract the construction of HttpClient away from its consumers, he specifically mentioned that he thinks the consumer should be responsible for constructing every implementation detail, which would lead to construction logic being spread all over the place.

We got into a few arguments due to similar design meetings. In one heated argument, I was even told that "[he has] been programming for more than 20 years!", implying I should not even dare to question his authority.

What I tried to mitigate this problem

  • Written detailed comments on some not-so-obvious components why I needed those and what purpose do they serve
  • Passively demonstrated that my design is much more adaptable to changes
    • A component that I built has significantly lower bug count than most other components
    • Correctly anticipated a change in requirements, which led to minimal code change necessary to fulfill that requirement
  • Addressed his concerns upfront when I am challenged by explaining my thought process and reasoning
    • However, I am still reprimanded for over-engineering code.
  • Informally discussed this with my colleagues and asked for their opinions in private
    • Most of them appreciate my well-reasoned approach and one even mentioned he learned a lot from me. Most of the engineers like to discuss their coding problems with me, because I can usually give them useful advice or point out something they might have missed
  • Holding informal presentations to educate my fellow engineers (and manager) on why I apply a design pattern here and there

I do not want to sound arrogant by saying my coding skills is absolutely better than my manager’s, but I have really run out of ideas to convince him, even after the demonstrations, the explanations, and the objective results being shown to him. On one hand, I would like to deliver bug-free, well unit-tested and designed code. On the other hand, I keep getting criticized for my design does not feel good and has certainly ‘complicated’ my code by forcing it to the ‘approved’ way.

How can we find a middle ground?


Update

Since I am getting a lot of comments mentioning about my dogmatic, even over-zealous attitude to follow software engineering principles, I think I should clarify:

I am not trying to be dogmatic nor overzealous. I do care about people reading and understanding my code, whether they use/understand design patterns or not. I asked for feedback from my colleagues during code reviews if they understand my code or not. They said they do and they understand why I design a component in such a way. In one occasion, my use of design patterns helped centralize the configuration lookup logic in one location versus having it spread out in dozen of locations, which has to be changed often.

To be honest, I am quite disappointed to see so many responses with a strong stereotype "Why you engineers can't think like managers". At the end of the day, every thing can be said to be over-engineering: Why mark fields as private instead of exposing everything, why unit test if no user is going to execute just a single unit, etc.

My motivation in use of design pattern or in fact any software engineering is to minimize risk and bring value to the company (for example by reducing the unnecessary spread of logic in the code base, so that they can be managed at one single location).

Sorry if this sounds like a rant. I am looking for answers along the lines of 'how can we find a middle ground' instead of some condescending answers like 'engineers think they are smart by applying design patterns which no one understands'.

8
  • 3
    Comments are not for extended discussion; this conversation has been moved to chat. Jan 11, 2018 at 3:38
  • 10
    A thing you don't mention that seems important: how experienced are you in software development? Specifically, how many years have you been practicing, and how many significantly different problem domains have you worked in? "Problem domains" are usually equivalent to "companies," but can be different projects inside a large company.
    – Jim Meyer
    Jan 11, 2018 at 17:40
  • 1
    Are others in your team able to modify/change your code as well as you are saying?
    – Dan
    Jan 12, 2018 at 19:11
  • 9
    @Fattie: This isn't a programming question. Not a single question about how to program was asked here. This is a question about an interpersonal relationship at a place of business between an employee and a manager. The conflict happens to be over programming.
    – Ellesedil
    Jan 15, 2018 at 7:14
  • 2
    Hi @Ellesedil - I disagree, but that's why there's voting!
    – Fattie
    Jan 15, 2018 at 13:57

12 Answers 12

250

Has doing it your way ever helped? Was there even once a time when you used indirection and injection and extra interfaces, and there was a last-minute swerve, and it was all handled smoothly and beautifully with no swearing? Even at a previous job, if you've never been able to get that code committed here?

I'm going to assume there was. Practice telling that story. It's specific and real. It's not "x might happen" or "y might change" but, "Once upon a time, I did it this way and here's how it worked out." Managers (I speak as one) are leery about spending money (and trust me, you writing more complicated code that others can't understand on a first pass is spending money) for what might happen. They don't want to fund speculation that may only be based on "book learning" and the latest fad according to the internet. But when you draw on your experience? That's a different situation entirely.

I am not a big fan of factories, providers, injectors and whatnot. They generally are set up for things that will never really happen (switching from MS SQL to Oracle) or have a small impact when they do (changing the folder where the files are saved). They do have a place in arrangements that are highly volatile, which you appear to be in. So you need to show that they have that place. You seem to be coming from a position of, "This is the normal way to do things, and I need a reason not to." Your manager is coming from, "This is not normal; normal is straightforward and simple. Give me a good reason to put another layer in the way." Work on that reason. Work on a past-tense really-happened success story where that extra layer saved days or weeks of work. Justify your engineering or else it really is over-engineering.

4
  • 1
    Comments are not for extended discussion; this conversation has been moved to chat.
    – enderland
    Jan 10, 2018 at 19:34
  • 2
    You cannot "switch from SQL to Oracle" since Oracle databases use SQL. Did you mean "switch from SQL Server to Oracle"?
    – MT0
    Jan 12, 2018 at 11:31
  • 32
    @MT0 you've obviously never worked with Oracle. shudder Jan 12, 2018 at 12:49
  • All complexity has a cost that should be justified by a clear articulation of value. I've found that when I'm not able to clearly explain why some complexity is necessary, either (a) it's not truly necessary, or (b) it doesn't do much harm to wait until the reason is clear to add the complexity in. Dec 12, 2021 at 2:40
173

This quote from one of your comments troubles me.:

As a software engineer, it becomes second nature to me to ‘do-stuff-that-may-not-have-a-good-reason-on-the-surface’, like interfacing the unknowns that I mentioned. Having to constantly be on the edge of explaining myself on deeply technical (and sometimes heavily opinionated) subjects drains me.

I've seen several repeats of the following life cycle:

  • Skilled programming team comes up with a different approach to programming.
  • It is viewed for a few years, up to a decade, as something that should be used universally, despite any downsides and limitations. During this phase, it is enough to say "I'm applying methodology X" without analyzing whether X is a net benefit.
  • It goes out of fashion, but its most useful ideas stay around as part of the software development toolkit, to be pulled out and used whenever they bring net benefits.

To my mind, both TDD and design patterns are hovering around the split between the second and third stages in the programming methodology life cycle. I am sure that TDD and many design patterns will have a long and valuable life in the toolkit, to be used whenever they help more than they hurt. I also think they may still be being over-used, by habit rather than deliberate thought.

You should never apply a design pattern because it is second nature, or have trouble explaining your use of it. Instead, before applying a design pattern, think through its costs and benefits in this particular situation. If its benefits really do outweigh its costs, you should know exactly why, so explaining the trade-off should not drain you. If its benefits do not outweigh its costs don't use it. Again, your own thinking about your design should prepare you to answer if you are asked why you didn't used a possibly-applicable design pattern.

Remember that you need to think about these trade-offs in terms of the overall maintainability of the program, not just getting your piece working quickly. Too much indirection can make it harder for future programmers to find out what is really going on.

12
  • 40
    +1 for the whole thing, but especially for the paradigm life cycle. When I started working objects were the end-all, be-all. Now, they're a useful tool.
    – Jim Clay
    Jan 9, 2018 at 15:58
  • 11
    Patterns are already moving into the third stage: softwareengineering.stackexchange.com/a/335894/92517
    – jpmc26
    Jan 9, 2018 at 22:17
  • 6
    @rexcfnghk Polymorphism, like the rest of OO, is just a tool that may bring gains or may add net complexity. Given only a dozen uses that can all be found reasonably easily, I would choose between editing them or adding polymorphism based on which results in the simpler, more readable, program. Jan 10, 2018 at 1:25
  • 6
    Agree with the need to justify, don't agree that a switch should be used in 12 usecases instead of polymorphism.
    – Thomas W
    Jan 10, 2018 at 4:35
  • 6
    it is difficult to understand as there are two implementations of an interface. huh that's basically the opposite of how I think about interfaces; I get suspicious when an interface doesn't have more than one implementation. I realize that's not the only reason to have an interface, but addressing multiple implementing classes in a common way has always been the main reason for me to use an interface.
    – jhocking
    Jan 12, 2018 at 17:56
61

Am I the only person perplexed at how in Workplace we're seeing so much focus on coding practices rather than the actual workplace conflict? So I'll take a different approach.

Here are the generalized aspects of your issue as I see it:

  1. You're in a skilled field that requires collaboration
  2. There are no documented procedures governing how this collaborative work should be done
  3. There is disagreement on how this collaborative work should be done
  4. One of those who disagree is your manager

It sounds to me like your group needs to get together and agree on what standards and practices you will adopt and to adopt them globally, for better or worse. Because nothing is worse for a product than a team that is constantly at odds, and nothing is worse for your relationship with your employer than constantly rehashing arguments with them.

So try to get your team together to agree on some standards, and use that meeting to plead your case for the practices you're using. If you get them, great! If not, then so be it. Your job is not to write beautiful code. Your job is to deliver a finished product. If your employer (as embodied by your manager) and a plurality of your group insists you do it a certain way, then who are you to gainsay them?

However, it sounds like most of your team agrees with you, so it should become pretty apparent during these discussions that your manager is the odd one out. If this person still refuses to change to the team consensus, then that's a dysfunction that we cannot help you solve (other than recommending you move to a different team).

6
  • 6
    You're right about the focus of the answers. Comes from so many of us being software developers.
    – Jim Clay
    Jan 11, 2018 at 15:10
  • 18
    I disagree that the sort of design question the OP raises can be handled by setting standards. Neither "Never use technique X" nor "Use technique X everywhere it is applicable" is likely to work well. Instead, any discussion should be on how to make trade-offs between quick implementation of new features and long term maintainability. Jan 11, 2018 at 20:20
  • What if you want to write beautiful code AND deliver a finished product? They aren't really mutually exclusive are they?
    – JeffC
    Jan 12, 2018 at 3:37
  • 2
    It was because the OP is very specific about how he engineers software. And the way he does it is not uncontroversial, there are a lot of sides to look at it and a lot of people with strong opinions all over the place. The question is also loaded: "How do I deal with a manager who refuses to use common design patterns....." And a lot of peoples gut reaction is: "because doing that would be stupid." So answering the question in how to deal with the manager would become an agreement with said practices. Maybe if the specifics of the tasks would be removed from the question it would be better.
    – Pieter B
    Jan 12, 2018 at 8:42
  • 1
    "Am I the only person perplexed at how in Workplace we're seeing so much focus on coding practices rather than the actual workplace conflict?" couldn't agree more.
    – Fattie
    Jan 14, 2018 at 16:04
24

Unfortunately, he's your manager, and you're not writing code in the way he wants you to write it. If he's management he might not be planning to be out of the company in 2-3 years like most developers plan to. You're writing code that will be harder for your replacements to fix, which is why he's hard on you for building it that way.

If I'm allowed to make an assumption here, knowing full well that I could be way off the mark, what are you writing this stuff for? I'd be rather surprised if it's anything more than LOB applications. Design patterns are probably way over-complicating some code for an LOB application that doesn't particularly need to be complicated.

In my 10 years of developing, a true strategy/factory pattern has been needed only three times, two of which are from jobs:

  • In an application which displayed product information, where some of those products were essentially a bunch of smaller products in a box, we used a strategy to determine which factory was needed to transform the product information (requested via a key) into a view. Not very glorious, but it did the job. If I'm allowed to match your humblebrag about bugs, in my entire tenure there we never had a single bug! (one was reported after I left but turned out to be user error :)).
  • In an application which showed users where to go for a class they were attending, we used a factory and abstraction to allow a quick shift between a Bing Maps API and Google Maps API. This was because both had a cost/benefit and the company wasn't making progress determining which to use. Eventually we heard from our home office we already had an API key for one of them and were able to pivot at the last second to that API, right before launch.

And a third is a project I'm messing with, which does server monitoring for Windows servers:

  • I use an interface for outputting the monitoring data and for the monitors themselves. The monitors are highly configurable (based on application settings). The output implementation varies depending on whether or not I'm testing a new monitor or going to deployment, such that IOutputInterface has ConsoleOutput and SqlOutput as implementations that can vary.

Note that my personal project immediately makes more frequent use of patterns and inversion of control (IoC) than my work projects.

If I can give you any advice after all that, let it be this: A job is a job, and if you want to do things your way then try to find a happy medium. Tech people don't generally stay places long and it's not worth the hassle of getting into a fight with management on how it's done. Have your personal home projects be a pattern pile as much as you want.

7
  • Good uses of the Strategy pattern.
    – Thomas W
    Jan 10, 2018 at 5:09
  • 3
    What does the abbreviation "LOB" stand for? Jan 11, 2018 at 7:09
  • 17
    Ive been on projects where programmers have applied design patterns everywhere, where previously there was 2 classes (an interface and an implementation), now there are 7. OP, do you really need a ProxyProviderDecoratorFactory ? You're raising the complexity level for everyone else. Your manager can see that, too. Google "YAGNI" and try to do things simpler. Jan 11, 2018 at 10:31
  • 7
    @ThorbjørnRavnAndersen LOB stands for Line of Business, typically an application used to support some kind of business process.
    – CodeMonkey
    Jan 11, 2018 at 11:23
  • @C Bauer "In my 10 years of developing, a true strategy/factory pattern has been needed only three times" I struggle to believe it, do you use any other way to implement polymorphims? Like templates/generics or function pointers? How do you apply the open close principle? Surely you cannot modify the interface every time a new functionality is needed? Jan 12, 2018 at 17:20
9

Easy solution: quit.

Hard solution: in any disagreement, half the fault lies with you.

Take some time off, study how other teams work, figure out where the impedance mismatch is between you and the other party. Talk to them in person, early and often. If you do this well, both you will learn to understand the other party's concerns and credentials, and they will learn to value you for your input, experience and stout opinions. Here are a few areas to consider:

  • quality product vs. time to market
  • good product vs. good code
  • smart code vs. self-explanatory code
  • top-down company culture vs. bottom-up engineering culture

If it doesn't work well, consider another role in the team, another team in the company or, finally, another company.

0
8

What should I do?

In software engineering, how well code is written (or over written) is always subject to some level of interpretation (opinion). To me, you are taking the steps I would in your position, but ultimately your manager is the one who needs to see the light....keep showing it to him.

I would continue, as painful as it may be, to do exactly what you are doing and point out the pay off in the investment in using the design pattern where you can, without making your manager look bad.

Do not change what you're doing unless you feel yourself at risk of worse than a reprimand. Keep showing them the benefits of using the pattern, and eventually they should come around.

As you continue the struggle, try to gain some other allies on the team. This way you are not the only voice heard speaking up for the pattern.

At some point however, if they refuse you have a choice to make as to whether this environment is right for you. I don't think you're there yet, but you may have to move on to an environment more acceptable to good coding practices.

Remember, this struggle you are in is a marathon. If you want to change the coding culture it will be up to you to demonstrate the value of the pattern.

12
  • 23
    Didn't down-vote, but I think suggesting that OP continue behavior which is causing him to butt heads with his manager, may not be the best advice.
    – cdkMoose
    Jan 9, 2018 at 17:12
  • 20
    Could also be a recipe for getting fired, which takes more than Advil. Persistence can be come insubordination if the manager has to say no often enough. Without knowing more details of the project history, it's not clear to me OP is entirely in the right here. Forcing good coding practices to a legacy project can still cause confusion and errors from other team members.
    – cdkMoose
    Jan 9, 2018 at 17:25
  • 2
    Every project does stuff the "right-way" and the "wrong-way". It just so happens that the "right-way" is frequently the "wrong-way" for many projects. Ignoring what seems to be clear direction from one's manager to do what you believe is the "right-way" is not going to work out well very often. Butting heads and persevering is not going to create a "happy" work environment. The correct approach is to first PROVE YOURSELF. It's much easier for someone with a reputation as a top-knotch developer who delivers consistently to get their ideas accepted rather than someone pointing to the internet.
    – Dunk
    Jan 9, 2018 at 22:10
  • 4
    I've witnessed a senior developer getting canned because he would go and implement features the way that he thought was best. The manager tried to explain the way he wanted things done a few times, then eventually kicked him to the curb. No one is irreplaceable, and compliance is often viewed as being more important than raw technical skill. And as my manager (he was a really good guy and didn't lightly fire the senior dev) told us afterward, "I need code that any of your guys could update/debug/expand on. A fancy solution that only 1 person can understand does more harm than good".
    – AndreiROM
    Jan 10, 2018 at 15:08
  • 3
    @IamSoNotListening You and the OP may find Repenning's and Sterman's Nobody Ever Gets Credit for Fixing Problems that Never Happened interesting. Jan 10, 2018 at 21:00
6

If you face these people head on you will face the greatest resistance, grasshopper. I've been most effective at bringing change when I strategically hit the right pressure points. It requires a lot of patience and giving in a lot. I must first adapt to them before applying pressure at the weak points.

Empty your mind, be formless. Shapeless, like water. If you put water into a cup, it becomes the cup. ... Now, water can flow or it can crash. - Bruce Lee

Listen to them and ask a lot of questions. Genuinely listening to someone takes away their desire to resist. Understand what motivates their thinking then speak their language. Since your beliefs are axial, at the moment, he is likely mirroring your stubbornness, contempt and frustration. Since you are sub-ordinate, it's his choice not to join your wavelength and onus is on you to build the bridge.

As you see him you will see yourself. As you treat him you will treat yourself. As you think of him you will think of yourself. Never forget this, for in him you will find yourself or lose yourself. - Helen Schucman

A Wing Chun Kung Fu master will draw his opponent in and close the distance before seeking and attacking the center-line where he is most vulnerable. Don't argue minutiae just to win, find the center-line of the bigger problem and focus pressure there.

I deal with engineers on a daily basis that refuse to retool or learn new programming paradigms and I've been given some form of "I've been here since punchcards" argument more times than I can count. I estimate I've lost 80% of the battles, but those 20%...woh...I've made big changes happen. I might sound vague, but do some google research on some of these keywords and you'll get what I mean.

Also, try to get on an new squirrel project that you can do it your way. If it really works and saves time or money people will come around to your way of thinking. If there is no new project, create one in your spare time to solve a pain point the company has and no one is interested in taking the time to solve.

1
  • I like your style. Analogy is a powerful tool, when properly used.
    – gazzz0x2z
    Jan 10, 2018 at 9:29
6

Firstly, we can't tell from the information given who is right. In fact, if I were called in to audit the project, I might still have difficulty deciding who is right, because you might be designing with different objectives in mind. But my guess would be that the boss knows the objectives better than you do.

Secondly, your question: "how can I persuade my boss?" The answer is, you probably can't. In the end, he's the boss. The only time I persuaded my boss to change his ideas on software engineering was after we spent a year patching an unreliable piece of software that was written the way he wanted it, and we told him we couldn't make it reliable except by designing it differently.

3

We don't know who is right here from a technical point of few - it could be a manager stuck deep in the past, or a new developer blindly believing all the hype.

But he's your manager, and you don't deal with the manager, you deal with his refusal to do what you think is best, and insists on doing what he thinks is best. And that's the normal state of things, that your manager makes the decision. It's also the normal state of things that he ultimately has responsibility for success or failure, and not you. He does have the authority. And he's right, you shouldn't question his authority. You can question whether he is right, but not his authority. So you either deal with it or change to a company that does things your way.

Meanwhile, instead of thinking that things don't go the way you want them to go, think about how you produce the best quality code that you can within your limitations. Many things can be done in different ways. There is "straightforward, badly designed" and "straightforward, well designed". Go for the latter.

2

Experience allows to judge if the benefits from the design pattern are possible and likely in the future. If the supervisor knows the pattern and still refuses it, he probably recognizes the case when applying this or similar pattern does not pay off. Sometimes experience contradicts the rules or more likely they interpretations.

There is a known opinion that shorter and more straightforward code is easier to understand and more open to significant alterations.

2

Basically what you are trying to do is have another layer of indirection, and another and so on. It do complicate things.

Do those layers actually solve a problem? Making it easier to add features in future is not solving a problem. Customer is not willing to pay for it. Therefore, its not a problem for business to solve. For business the problem dont exist.

Besides it cannot be done. There is no telling what particular feature customer may want in future. When you design a product in a special way you do make it harder to add certain features. Its better to keep design open.

So, you are not only doing an unauthorized investment on behalf of your company but you also have no idea about the risk factor involved.

Complicated things need more time to be done and maintained. Time is money.

Complicated things limit how much and of what type of other things can be added in system. If once you go on the path of making things complicated then you have to make other existing and new things complicated too even when they themselves need not be complicated.

There is one last message in this. Its said that the number two dont exist in computer science. If a thing has two variations you dont add another level of indirection. You just let the two variations exist. Its simpler that way. Unless you have three or more variations the commonality is not clear so you dont abstract it. You dont know what to extract, you are taking risk and doing wishful thinking.

0

I would suggest pair programming and peer review. This will help your coworkers understand your code better, as you need to explain why and how as you do it as opposed to after the fact.

Either they will learn from you and see why it is smart, or you will learn that the best programmers write code others can maintain.

4
  • 4
    This presumes they don't already understand, but they may simply not agree with the necessity for it or that they think it's not cost effective. Also the OP cannot impose a production system like pair programming on the enterprise. At most he can suggest it. The OP seems blind the possibility he's simply wrong and may be missing the big picture. Jan 11, 2018 at 6:36
  • @StephenG There clearly is a lack of OP being able to communicate why his approach is objectively better, and in turn understanding why others think his design choices are non-optimal. Pair programming is perhaps the best way I've found (in the few cases where it was beneficial for us) to be able to discuss the design process as it happens because you can challenge each decision as it is being made if you don't both agree. This may well be the case of "A thousand stitches in time saves nine". Jan 11, 2018 at 6:44
  • 4
    To me it sounds like the OP has communicated his opinion too much and too aggressively, but has had the opportunity to do so. He sounds like he lacks the soft skills (and perhaps patience) required to get things done the way you want in an organization you're not very senior in. His boss actually sounds exasperated with him - time to calm things down and show he respects his boss, not push more - he must prioritize maintaining good working relations over his personal technical opinion (which does sound extremely opinionated whatever the technical merits may or may not be). Jan 11, 2018 at 6:55
  • @StephenG Perhaps. That is why I am turning this into a mentoring situation, where the hopefully more experienced senior developer can point out where the chain of assumptions by OP fails. Jan 11, 2018 at 7:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .