Many projects start with a lot of question marks. For example, when the requirement is: "I need a graphical user interface to manage the contents of the menu card", then many questions are already answered - at least it seems that way. But when the requirement is: "I would like to open a French fries stand" or maybe even "I would like to open a French fries stand and need the software for it", then every developer probably faces a lot of questions at first. Where should you start and where should you stop? What actually happens in a French fries stand?
Well, a French fries stand is quite simple. There are French fries and maybe some other food and drinks. That can't be difficult.
Or so people think. Let's take a closer look. And so that it doesn't get too complicated for this article, let's assume that our French fries stand really only serves French fries - and mineral water (cola is unhealthy).
Business Processes
In the first step, let's try to understand the most important business process, which is the preparation of fries. We definitely need a freezer for this (we'll just ignore the question of whether the mineral water needs to be refrigerated for now). Well, if the fries are frozen, then indeed we need a freezer, but if the fries themselves are prepared from fresh potatoes, then we don't.
Next, we need a deep fryer. That's true if the fries are deep-fried - frozen fries, however, could also be prepared in the oven. However, whether homemade fries from the oven taste good is questionable.
Where do the fries actually come from? Are they delivered or picked up? How do we know when to pick up - or order - new fries? We can't answer that at the moment, so we'll put the question on the back burner for now. It's probably not part of the core business process.
Once the fries are prepared, then they are served. Will paper plates, plastic plates or porcelain plates be used? While we probably don't want to reuse paper plates, it would be rather uneconomical to throw away porcelain plates after each use. So we need to clean them. Do we do this by hand or with a dishwasher? What kind of dishwasher is used and how long does it take to clean a load? That's important, because we have to have enough dishes on hand to get through the lunch business. It's also interesting to ask where we store the used dishes until they go into the dishwasher.
Not so simple at all
We can see that a (seemingly) trivial business like a French fries stand is not so simple anymore when we take a closer look. An experienced operator will have answers to most or even all of these questions, but in many respects one will ultimately depend on the number of customers; or more precisely on the maximum throughput - i.e. the number of customers per time unit.
It becomes much more difficult if we want to open a French fries stand for the first time and have no experience in this business field. After all, there are numerous other questions that need to be answered: Where to put the waste? Where do we get electricity and water from? What legal obligations must be met (for example, hygiene regulations)? Do we only accept cash or also credit cards, debit cards, or perhaps bitcoins?
Do we accept pre-orders and do we offer low-salt fries for health-conscious customers? Where do we even get our customers from? What are we doing to keep our customers coming back? Is our French fries stand fixed or movable? What are the implications of this?
How many staff do we use to run the French fries stand? How do we account for their salary? And what records do we need to keep to keep the tax man and tax office happy? Do we have to keep records of how many portions of fries we sell each day, or is it enough to report the total daily revenue to the tax office?
You have probably just learned the most important lesson? There are no simple business models when it comes to software. The closer you look, the more worlds open up. And there are unanswered questions everywhere. The biggest mistake you can make now is to go ahead and develop software without a solid understanding of the business model and business processes. The result, even if the software were to be absolutely bug-free, sustainable and easily maintainable, would probably be "right" by accident. How can you develop the right software if you work into the blue?
Impossible is not acceptable
Software is in a certain way very rigid in terms of adaptability to changing business processes. Of course, you can have the customer assure you that they want to make the fries themselves. But if, after two weeks of stress during operation, the customer realizes that they want to make frozen fries from now on, then the oven has to be removed and the deep fryer and the freezer have to be installed.
Of course, such changes are easier to implement in software than in hardware. Perhaps this is what drives us again and again to make technical decisions far too lightly. If you use a relational database, for example, you have to use SQL. A search engine is better suited for many use cases than a relational database, but understands a completely different query language . So technical choices have consequences, including in the form of interfaces that we submit to.
It is therefore important to keep technology and implementation details out of the discussion for as long as possible. This is not always easy for developers. We like to think about what could be possible at an early stage. Then, in the discussion with the customer, it is always said "yes, we can implement all of that" - but the customer does not realize that the developer was talking about alternatives here, and that it is by no means easy to meet many different requirements with one system.
Interestingly, it is also very easy to get around technical dependencies in the implementation. The key to success here is abstraction. If all SQL is concentrated in a few classes, then not only are the queries very easy to test (in isolation), but the rest of the application knows nothing about the fact that a relational database is being used at all. For this to work, you need to understand the D (Dependency Inversion) in SOLID correctly. This is not only about " Dependency Injection ", but about the question in which direction dependencies point.
If an application's business logic "knows" the database (or any other persistence mechanism ), then this is a dependency in exactly the wrong direction. Dependency inversion in this case states that the business logic must not depend on the data access, but the data access must depend on the business logic. To achieve this, both must implement a common interface that must be defined as part of the business logic.
Once you draw this up with boxes and arrows, you can see that a classic layered architecture propagates exactly the wrong dependency between business logic and data access. If you've wondered where application maintainability issues come from in this tension, you now have the answer.
That's the price you pay for making technical decisions too early, making you dependent on technical details.
But after all, we haven't started realizing it yet in our "French fries stand" thought experiment. Nevertheless, developers often tend to have a far too technical discussion with the customer. "We can map this m-to-n relationship into the database without any problems, and with the right indexes, we won't have any performance problems" - these are all technical details that the founder of a French fries stand is certainly not interested in, especially since he probably doesn't understand them in the first place.
Language Convention
So we have to get away from technical details and jargon. It would be much better if we could meet the French fries stand founder in their world. So why talk about any technical terms? We would be much more customer-friendly developers if we spoke our customer's language - and only their language, without all the technical stuff.
But that sounds easier than it is. If we have more than one contact person, the whole thing quickly becomes confusing. Let's imagine that our customer is a French fry company. We call a meeting to clarify the central terms and their meaning. After a bit of preliminary banter, we ask our central question: "What are French fries?"
A chef present answers, "Deep-fried potato strips," and briefly talks about how fries have to be deep-fried twice at different temperatures. The controller talks for a while about the cost side of fries until he is interrupted by the buyer. The latter explains that the purchase is made by the bag, whereupon the QA manager fabulates about his constant worry that the cold chain could be interrupted. The accountant is mainly interested in the VAT rate at which the French fries are sold. In short, the meeting does not produce any meaningful results, even after two hours. What went wrong?
Finding a common language between development and the customer is also so difficult because the customer's various stakeholders do not even speak the same language. There are different contexts in which the same terms can have completely different meanings. While one person sees fries as an ingredient for a meal, to another they are simply the contents of a bag that need to be moved. People may talk about the same things, but each has a completely different image in mind. This quickly leads to misunderstandings.
It gets particularly bad when developers try to map the completely different requirements into a uniform object model. This would lead to extremely bloated objects. Purchasing and warehousing are likely to be interested in the expiration date and storage period of French fries, while a chef would probably at most check whether the fries are still shelf-stable before opening a package as a quality assurance measure. For the cashier, a portion of French fries is simply a certain price, perhaps with a VAT rate added depending on the situation.
In order to develop software successfully, the different contexts must be neatly separated. Software should not span several such business contexts. To do this, of course, the contexts must first be identified. This is done using "language boundaries"; within a context, a term has a specific meaning. Where the meaning of a term changes, two contexts border each other. Contexts often coincide in companies with different departments, but just not always.
What if we designed important business objects to combine aspects from different contexts? The result would be extremely complex, heavyweight, and poorly coherent objects, i.e., objects whose various attributes and methods have little context. The single-responsibility principle alone would demand that such an object be split into several smaller objects, because there are several reasons for a change.
Once again it is shown that smaller objects are the better objects. And the more these are aligned with actual use cases, the more efficient software development becomes. "Maximize the amount of work not done," it already says in the agile manifesto . The consistent design of software based on use cases is an important prerequisite for this.