Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Business logic is slowing us down
31 points by headwind 4 months ago | hide | past | favorite | 40 comments
As developers, we're caught between keeping up with our internal stakeholders (operations, business, and data teams) and satisfying external end users. We spend a nontrivial amount of time maintaining our code to keep up with complex, ever-changing business logic.

Do we really need a code change for changing what triggers which user notifications or for updating how something gets named/logged in the database?

Unfortunately, maintaining code is also not considered valuable work. We're valued for pushing out new features, and keeping existing features up to date with changing business logic is considered short work.

To be great devs, we need to understand our users (including internal stakeholders) and our industry domain. But we also need a better way to empower business teams to control and manage the business logic, while clearing the runway for devs to build the next feature.

How has your team handled this?




A lot of this comes down to poor product management.

A shitty PM sees problems like "when a guest at a hotel room completed {specific action X}, they want to receive a notification saying {specific message Y}".

A half decent PM will stop, step back, and ask "is there a meta-pattern here that I'm just not seeing yet", and realise the actual requirement is something like.

"When a guest at a hotel is the subject of any meaningful business event related to their booking, the management of the hotel want to be able to send them some kind of configurable, context-bound notification containing information about that event (ideally with some simple conditional logic to skip scenarios where the notification isn't relevant).

As an engineer, you're going to look at those two requirements fundamentally differently, and sure, the second one is maybe 3x harder to implement initially... But once you're 20x different "bespoke notification events" deep, you're gonna bloody wish you built the second option from day one.

Src: am Snr PM who sees teams get screwed by this type of bad PM thinking all the time.


"A half decent PM will stop, step back, and ask "is there a meta-pattern here that I'm just not seeing yet", and realise the actual requirement is something like."

Not going to lie, this is the funniest thing I've heard all day. I've met maybe 1 PM in my entire career that actually thought that way, and that was at the beginning. The longer I'm here the more they seem focused on speed and metrics and less on the actual sysrem.


What are their incentives? Are they switching off to another product quickly, or are they staying with this product for years/decades?

Do they get rewarded for long term thinking or short term results?


Almost nobody gets rewarded for true longterm thought. Devs, PMs, etc aren't going to stick around waiting for a promotion, raise, or bonus for work they did 3 years prior. They want their comp now for the stuff they did this year, even though you won't see the true longterm outcomes for years to come.


But "YAGNI" has completely brainwashed the mind of "the lazy developer" so option (2) is seen as "resume driven development"


YAGNI includes time to fix things when YNI (you need it). YAGNI is not prematurely optimizing for complexity.

If a PM (or an eng for that matter) can justify the need for the complexity, either because they are extracting 2-3 use cases in to a generalizable solution, or they have 1 but know that 2-3 or more are coming real soon, then bring on the complexity.

It's a balance, for sure.


I think both are valid, and in the balance. At about 3x deep we know there will be 20 or more.


I agree with that. I think the rule of thumb is:

The first time you do it, just get the job done as described. The second time, look for ways the two might be similar, but don't spend a lot of time on it. The third time, generalize and assume there will be a fourth, fifth, sixth, etc. time.

In the example the top poster gave, the first time it was requested, I would just write up some code for triggering the notification. The second time, maybe there's a shared class (or whatever) for notifications with text passed in. The third time, now maybe we need the ability to specify notification text in config or DB or through user-triggered actions.


Ideally, the business should have their processes defined before ever implementing them technically. So these architectural questions should mostly be addressable from the start. Knowing hoe the processes look upfront can actually lead to some wonderful designs rather than constant reactors. We had a system that we knew from the start would have multiple UI layouts for multiple workflows that shared mostly similar data. We were able to build the UI to dynamically build the pages based on the data.


To be clear, I'm NOT advocating for premature abstraction, as a PM I live and die by "rule of three" when making decisions re: "let's just quickly solve this one bespoke need", vs "let's think about this more systematically".

But customers will never tell you all their requirements up front, and it's a PM's job when hearing a need from a customer to take the time to figure out if it's a single unique stand-alone problem, or simply one instance of an entire category, the other 3687 of which your customers are going to come asking for the moment they realise it's a category of problem your product is able to help with at all.


Perhaps it’s better to ask what will put the greatest cognitive strain on the developers.

Generally I want to program for the specific case first and hopefully make it so small that it doesn’t hurt to throw it away when the requirements change. But if the specific case means the whole team has to be burdened with a lot of really obscure hospitality domain knowledge, maybe it’s quicker and easier to build the abstraction.


Right, this is why a bad PM is worse than no PM. "Just build this one use case, and since it's so simple, I promised it by nex week". Instead of digging deeper, as you suggest.


You're conflating different things here. What triggers user notification is business logic. How something gets named/logged in the database is not.

If your stakeholders don't understand the value of maintaining work and don't have budget set aside for that activity then that fail is on you (maybe not you personally, but your technology organization).

Empowering business teams to control and manage actual business logic, is a great idea but it doesn't come without its caveats. There's no Silver Bullet, that logic has to be stored and maintained somewhere. That logic has to have an interface to it that's callable by your system. Those interfaces need to be well-defined and everybody needs to understand exactly how the business logic affects the runtime operations. That business logic also requires version control management and release management. You also need a test environment. Guarantee some dumb ass will "fat finger" something and push it out and your system will come crashing down. If you can't roll back that change or restore the previous logic - your life is going to be hell. And do you know who's going to get the blame? You. It's your fault for letting them do something stupid.

These problems are enough to scare most people away from this insanity, but in case you're still persisten there's one more hurdle facing you: performance. You're taking logic that is currently hard-coded in with the rest of your program execution environment, and you're outsourcing it to another execution environment that has an API of some kind. Imagine what exporting the condition of an IF statement to an API is going to do for your performance! It's insanity.

I've seen many shops go down this path and I have yet to witness success. What you're advocating for is worse than the problems you have no. Sorry mate. Oh, and if you talk to IBM, they'll swear up and down that they have a tool that can do this. It's crap. I've been down that path. I've been down that path with Oracle, too. And various open source projects.

If anyone reading this comment as a different experience, a successful experience, then I'm all ears - I would love to hear it!


My experience mirrors yours. This is pretty closely related to the "visual programming" discussions we had on HN the other day.

Another observation: If you do not have competent engineering representation in owning business units, no amount of rearchitecturing will save you. On the other hand, if you do manage to have decent engineers in each owning team while maintaning quality of your core/platform and don't wreck incentives and empowerment, things have a larger tendency to sort themselves out.

It's when you shuffle your actual insightful engineers into middle/upper management and put helpless "Senior Engineer"s in charge of entire projects with a clueless PM or burnt-out-and-checked-out ex-dev in the middle that things go south.


Have any of them tried feature flags or other approaches? Curious what some shops have tried.


Learn to manage the managers. In some companies, this simply isn't possible. Org charts are like software architecture too. These have to be engineered by the person at the top, and you need things like servant leadership. Bad managers should be removed.

Code complexity goes up with more features. But also product complexity. I was actually looking for a product that did X for my residential community. My previous job did WXYZABC. Our community went with the crappy competitor that only did X and did it at 200x the price. There were lots of features because we learned to build fast and the price was low because the costs were low. We could have charged the 200x and conquered 80% of the easy market, but we went for bigger markets that we could barely reach.

I think the ideal is having teams that do only one thing. People love to talk about how efficient WhatsApp is, creating billions of dollars of value with like 40 people or whatever it is. But nobody wants to build a WhatsApp. They all want superapps, even though these are less efficient in every way.


Internal stakeholders are still users, and if they have a constant need to change business logic flexibly and without involving the devs every time, maybe it's time to build them a configurable workflow?

It might be worth taking a look at other self-service flow builders like the kind commonly used in marketing & analytics, where you set up a customer journey tracking page to page and write different rules depending on it, or where you set up an email drip campaign based on various configurable criteria.

The more generic and less usage-specific version of that is something like Zapier (for non-devs) or Make.com (for devs).

With that sort of abstraction, I guess your devs end up making a rules engine with a GUI and a bunch of modular nodes and integrations, like "if marketing software sends this webhook" or "send transactional email" or "increase customer value in CRM" or "notify staff to call this person", etc. that the powers that can then clobber together in whatever way they like.


Business logic is real programming.

What you described (non business-logic problems) is just "coding" level where you might integrate/compose libraries together at the boundaries of the system.


Exactly. What the OP is saying is: my users are getting in the way of my programming. This is nonsensical. Giving business users good tools to do their job is the whole point of software development. Implementing those tools is our job as developers; but the end goal of the software should not be changed to make development easier.


To be clear, every dev must understand and delight their users (including internal stakeholders).

But we also need a better way to empower and serve business teams by letting them control and manage the business logic. Keep in mind, we slow down the business teams if we cannot implement fast enough.

Carrying the mindset that devs must own everything can be harmful and counterproductive. In this case, there seems to be a mutual benefit to both sides. If you don't believe so, let me know.


Without a business generating revenue, there is no need for programmers.

Business systems need to be architected around core business needs, e.g. ledgers, journals, client records, inventory. The "transactions" implementing business rules need to perform the necessary information transformations and maintain any auxiliary information as required.


The core of the problem is that engineers do not own their code. It would be like a chef not owning their food. Engineers are split into teams that the business side of the company decides arbitrarily... and because non-technical leaders are not as familiar or knowledgeable about computer science, they create incorrect abstractions that constrain the solutioning for no reason.

Imagine an app where you have feature A, B, C, where A and B are basically the same feature with a few differences, and feature C is completely different. The business side of the company might decide to create three teams, one for feature A, one for features B + C, and another for features A + C. The engineers in each of these teams are immediately setup to create complexity in the long run because the correct abstraction would be A+B and then C.


Right, why wouldn't it be best to let the business logic live with the business teams?

I agree with team ownership. Unfortunately, teams and their ownership domains are organized in odd ways due to business needs.

However, that suggests to me that there's more reason to house the "ground truth" with the team that owns the ground truth.

If 3 teams each own different features, they'll each write their own business logic.


I would say there are different "ground truths". For engineers, this is computer science theory, and for business, it's what makes sense from a market perspective and what's best for the customers. This is why having engineers worry about customer needs is a huge mistake, at least in my opinion, because it takes away from engineers focusing on what they do best.

The solution could be something like creating two distinct domains, and then bridging the gap. You would have the engineering domain, in which abstractions follow information theory, and then you would have the business domain, which follows whatever the business wants. Then you would need some kind of bridge, whether it's teams or roles in each team, that translate and mediate back and forth. This way the business can ask for XYZ feature, the bridge teams or roles would then consult with engineers how to break these up, and then engineers would implement it. Additionally, engineers would have complete ownership over their domain.

I think the reason it doesn't work that way, is because the business side wants complete transparency over engineers, which constrains them for no reason. I also think these constrains are impacting the business value in the long run because software isn't being used to its full potential.


That chef analogy doesn’t work.

In any high end restaurant the menu is determined and then there’s a hierarchy of people who “implement” whatever dish.

The engineers are the line people. They’re not setting vision and they’re not doing anything beyond shipping code which is arguably like 10% of running a business, even if it’s a “tech business”.


Sure, you're just adding resolution to the example. If restaurants worked like many software companies, the chefs and cooks are still cooking and dealing with the food, but also running the food, taking the order, and cleaning the kitchen, while the owners decide on the menu and who gets to cook what food.


It sounds like a lack of coherent design strategy. That is the sacrifice feature driven projects face. A problem which usually wears in after about three years. After market entry yet right when regular additions pile up and begin to cross paths.

The solution is a maverick mind who can drive coherent code strategy.

Business logic isn't your problem, an unfaithfulness to the idea that the application is first a business logic machine may be. User interface should be a layer, instantiating and manipulating a logic API.

Configuration over code is one ideal philosophy. Design such that configuration may established what types of things, or where they might route.

This would only work if all parts of the application agree on a configuration convention.


Where have you seen configurations housed? Are there any great solutions for where to store configs so that business teams also have visibility?


The way I like to do it:

- use a config library (or write your own) it should read the settings.config from the root home folder.

- This library should also read settings.local.config (or equivalent.) make a git IGNORE rule for the settings.local.config so you would put credentials here and they won't be checked in to the repo.

- This local config should be read and merged into the base config by your config library (deep merge).

- Further, I like to pull additional config from the DB (for user level settings.) the fs is necessary for bootstrapping into the DB, which then may load additional preferences.

- This config format should be whatever you're comfortable with, JSON , YAML, TOML, .py/js, etc. your stack will have its own selection (and behavior) for config libraries.

And now, make sure that config is loaded and made available at the earliest point in code, and everyone can use it EASILY.

You could have this stashed into a user or system cache which your tools can then spy on to see what settings are available whichever place in code.

Settings, access control, preferences, etc. can all fit this format.

By using the git excluded '.local.' layer you can ensure API keys are never checked into git.


* root home folder; that's the application home, one level ABOVE whatever passes for web root. This file should not be accessible to anyone outside of the application.


We’ve done this using Django’s admin portal to let non-technical stakeholders work with database records, and it works well enough. It creates a self-serve scenario for some users, for some kinds of tasks.

The challenge is (as always) finding the right level of abstraction. A premature, wrong abstraction is way worse than making it work by hard coding some logic in the code, or (gasp) just copying and pasting the code a few times, until it’s clear which direction the abstraction is pointing, and at which level it’s operating at.

Like if you start building some generic workflow engine that doesn’t match your actual needs, you’re going to build something that’s clunky to work with, and that it’s hard to backtrack from the design decisions made. It’s better to hard code or duplicate something and remain noncommittal about architecture and design choices until you have clarity.

In practice it’s always a dance. You have to push the boundary to some degree or you’ll never build anything tangible. The usual advice of “just ship something” is not bad here, as shipping a complete failure will be a more information-rich data stream about the right direction than more planning.


Stories that might help.

Back in the 1980s I was tasked with writing a system to use a handheld computer to track the manual inspection of Fire Equipment (Extinguishers, Hoses, etc) at various locations across fossil fuel based generating stations.

The very first version was hard-coded to the questions they supplied. My initial estimate was 1 month, it took 2. It met the requirements we agreed to, but it was totally unusable. Any changes to the questions required changes to the source code.

I ended up providing them with a set of forms they could use to edit questions. (This is back in the days of MS-DOS, so it was all in a TUI). To handle the ability to actually add/remove questions, I provided a set of choices for question types (Yes/No, or a number)

Then I provided 2 options, the step number to go to if the right answer was given, and the step to go to if the wrong answer was given.

It wasn't perfectly safe, they could jump to a non-existent step number, but it was easy to comprehend, so they didn't have issues fixing their own errors.

It worked well enough to set up for 10 other stations, and paid my bills for a few years.

---

Another time, the Account Managers at the Consulting Firm I worked at wanted a number of reports, all of the same general format, but with specifications that varied all over the map.

I built an SQL Query generator for them in Microsoft Access, that built (based on their selections) and showed (and allowed them to directly edit) the resulting SQL query. They were then able to cut/paste and save the queries that they liked, and build new ones on the fly.

---

If you can build a tool for them that lets them define some event, then a series of steps that should happen afterwards... they can manage the business logic directly.

Your task isn't to make it perfectly safe, but transparent enough so they can understand and build a mental model of how it acts, so they can manipulate it safely.

They need to be able to see the current rules, and perhaps even play with them in a reversible way, to test out new ideas.


I’ve worked for companies whose processes resemble what you described. It wasn’t bad at all. Things were delayed, sure, but it wasn’t a big deal (I never worked extra hours). I actually enjoyed it because it was pure joy to implement features with unclear requirements because that gave the engineers maximum flexibility (if something wasn’t implemented as needed, we would just say “alright, we’ll work on those new requirements, no problem, another sprint will be needed, though”

On the other hand I have worked for companies with a strict software development process. I’m not talking about waterfall, but agile: the systems were so over engineered that it was very difficult to write code (and it was an awful experience). Everything was done by seniors who left the company some time ago. You couldn’t really complain if you needed more time to implement something because our PMs were very clear about the requirements (so, if delays exist that’s not on them), and the code was written following good practices and standards (so again, if delays exist, is not because of the state of the code base).

I prefer to work for chaotic companies for a couple of years: more flexibility (so I can actually enjoy writing code) than for companies with obsessive practices.


I'll dust off some old replies:

On "How to properly manage a product roadmap": https://news.ycombinator.com/item?id=22827841

On "Should you listen to your customers": https://news.ycombinator.com/item?id=26814150

On "How to effectively get feedback from users": https://news.ycombinator.com/item?id=24971875

These mainly delve into extracting the job to be done, avoiding the XY problem, and looking at actual user behavior (actions or lack-thereof aka "non-consumption") to turn into issues/tickets to solve real problems as opposed to imaginary ones. You can even encode these in issue templates / ticket templates to avoid having frivolous feature requests or unimportant/non-urgent bugs and focus on things with high frequency and/or severity. i.e: product management.

Now, for the engineering side of it...

On "How do you develop internal tools for your organization?": https://news.ycombinator.com/item?id=29061808

The above link shows the inception of our product around a plugin architecture.

More on that: https://news.ycombinator.com/item?id=25186586

The design principles I had set and enforced with iron fingers. The fist of someone who presses on keyboard keys may be weak, but his fingers are ruthless.

https://news.ycombinator.com/item?id=29397405

One way to go about this is to improve the way you build product (product management, everyone is involved) or push for that, then get the engineering to deliver that in ways that make it easy to add/remove features, integrate with users (in the abstract sense, they could be humans or other systems), onboard developers.

Other posts you could cherry-pick from can be found here: https://news.ycombinator.com/item?id=40482961


The naming thing has been handled since forever - use a code for the field name and display the business value associate with it.

The business logic understanding has been handled, but rarely implemented. Any technical system should be built off of a business system. The business should be able to define their business process maps and data points exposed in each step of the map. Most systems will still need devs to implement this unless you go with some no-code/low-code process map system.


Working on teams large and small, it's an effort. Larger companies block chunks of time to discuss this subject. Start-ups prioritize customers. One suggestion is to take ownership over tackling tech-dent or documentation. Express to your immediate team what you want to accomplish and provide some generic process to implement. It's never easy but make the effort to at least attempt solving this. Good luck!


A bowl of word salad, clickbait title and expectation to get some real answers from HN community, really?


Is considered ‘short work’? What does that mean?

You need to have a conversation with your colleagues about how much capacity your development team has.


> Unfortunately, maintaining code is also not considered valuable work. We're valued for pushing out new features, and keeping existing features up to date with changing business logic is considered short work.

Then don’t maintain it and just let it fail. Maintenance requires time and effort which costs money that someone has to pay for. If the customer/client/employer doesn’t want to pay for it then just don’t do it. Don’t be soft about this. Someone pays for this deliberately or it does not happen. If they feel emotionally conflicted they can go fuck themselves until business failure and lawsuits become the new norm.

Now, it is your responsibility, as the developer, to achieve competency. If the cost of maintenance exceeds a given percentage of total labor then one of two things must happen.

First, is resolution. Solve for the problem by proposing refactoring as a new feature. If they don’t want to pay for this then continue to let Rome burn.

Second, is ownership. Someone needs to take ownership of these expenses. I mean financial ownership on paper. That person(s) will be the one best positioned to address the concerns of maintenance, because maintenance costs money. Lowering the cost of maintenance requires research and measuring things. If nobody drives that deliberately it will not happen. If you as the developer cannot deliver the labor to achieve this then you should be replaced by someone who can.

That is all you need to know.


Take ownership.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: