<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>James Eastham | Just a storytelling technologist thinking about systems, software and people.</title><description>Just a storytelling technologist thinking about systems, software and people. Architect, international speaker, computer nerd.</description><link>https://blog.jameseastham.co.uk/</link><atom:link href="https://blog.jameseastham.co.uk/rss.xml" rel="self" type="application/rss+xml"/><item><title>An Ode To Building What Matters</title><link>https://blog.jameseastham.co.uk/blog/2026/2027-09-17-on-building-what-matters/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2027-09-17-on-building-what-matters/</guid><description>What was the original purpose of software? Why did the industry come to exist in the first place?</description><pubDate>Thu, 17 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;What was the original purpose of software? Why did the industry come to exist in the first place?&lt;/p&gt;
&lt;p&gt;It was to make things easier for us. To address the things humans aren’t very good at. A bit of yin and yang in the world. Us humans, typically, are great at empathy, at communication, at relationships, at critical thinking, at creativity and at novelty. Empathy as the most important. We have this amazing ability to see someone else’s point of view and understand why we might feel something/take an action if we were in their shoes. Although a lot of the problems in the world today come from people not doing enough of that.&lt;/p&gt;
&lt;p&gt;There are things we humans are bad at though. Imagine I asked you to just receive some forms people fill in, validate the data, do a bit of calculation on the input and then send the output on. And that’s all you’re going to do every day, for 8 hours, 5 days a week. Aside from being bored out of your mind, you’d also probably do it wrong. That’s not a slight on you, dear reader, or on the fact that these roles do need to exist, it’s just a reality of human nature. Most of us would get it wrong. Alongside that mundane task, if I also asked you to store in your mind every piece of data you come across whilst processing the inputs, and be able to regurgitate it at a second’s notice, you’d think I was mad. Our brains are great processing machines, and they do a pretty good job at storing information… Recall and working memory let us down.&lt;/p&gt;
&lt;p&gt;We can’t run complex algorithms in seconds, and sometimes our emotions affect our decisions. Sometimes, this is a good thing. But herein lies the problem with the current state of the &lt;strong&gt;majority&lt;/strong&gt; of the tech industry. The people in charge, the people leading, the enormous, capitalist, make money at all costs organisations have forgotten this. Software, computers, technology… foremost, they should make people’s lives better.&lt;/p&gt;
&lt;p&gt;I’m reading Enshittification by Cory Doctorow at the moment (highly recommended, as is his &lt;a href=&quot;https://pluralistic.net&quot;&gt;blog&lt;/a&gt;). The case study on Google is fascinating. In court hearings, internal memos came out that showed Google actively pushed to make Google Search results &lt;em&gt;worse&lt;/em&gt; in order to make you search more often. You know what happens if you search more often? You see more ads, which means Google makes more money. Similar stories exist for Facebook (leave MySpace and join us, we promise not to spy on you), Amazon (you can buy anything, and we definitely won’t undercut the sellers) or Apple (spying on people is bad, buy an iPhone, but we will also spy on you).&lt;/p&gt;
&lt;p&gt;The ‘personal computer’ should be something that is filled with things that are personal to us, that help us. Not subscriptions that we pay for a below-par service that is getting worse. But hey, if the stock price goes up, that must be good, right? I realise I’m saying all of this as someone who has worked for two big tech companies. It’s why a couple of paragraphs ago I used the word &lt;em&gt;majority&lt;/em&gt; of tech companies. I’ve seen both sides. I’ve seen the enormous, capitalist, make money at all cost organisations (hey AWS) and seen what a tech company looks like that cares about its people and in the main builds products that make users’ lives easier.&lt;/p&gt;
&lt;p&gt;This isn’t a slight on people on the ground at tech companies either. There are thousands of brilliant people at these companies. But a mandate from above to push AI into every single crevice of every single part of every single product doesn’t leave these brilliant people with much choice. Because remember, in 2026, if your product doesn’t have an AI chatbot, it’s worthless (also said as someone who is actively working on an AI chatbot).&lt;/p&gt;
&lt;p&gt;None of that is to say the technology itself is the problem though, it’s how, and why, it gets used. There are genuine, brilliant use cases for LLMs and the chatbots built on top of them. The human weakness I mentioned earlier, that recall and working memory let us down? That’s one of the things an LLM can be good at solving. Summarising huge amounts of random information into something a person can actually digest. Used well, a chatbot isn’t there to keep you searching for longer, it’s there to get you to the answer faster so you can go and do something more useful. That’s a good use of the technology, and it’s the bit of this whole thing I still believe in. Although, when said chatbot has a habit of making things up and hallucinating things do get a little less valuable.&lt;/p&gt;
&lt;p&gt;There is a paradox with the current use of large language models (LLMs), particularly for software development. It gives a huge number of people the power to take back some element of control and build systems for their personal computers that are personal to them.&lt;/p&gt;
&lt;p&gt;I’m a trustee of a local food bank, I manage all of their IT systems. Recently, I’ve built some custom software for them. Nothing fancy, at it’s core, it’s a database with some validation on the frontend that can send automatic text messages. Previously, with a full-time job, I wouldn’t have had time to build it. The food bank would have gone on with a pretty inefficient process, or bought some cloud subscription that kind of gave them the right functionality but not really. AI coding assistants enable me to build something that works for me. It’ll never be sold, we’ll never charge a subscription, we’ll never ask people to pay for it or enshittify it and sell everyone’s data. We’ve just built a tool, that makes everyone’s lives easier.&lt;/p&gt;
&lt;p&gt;Whilst I’m not suggesting you go and try to build the next Amazon/Netflix/Google/Uber with your laptop and a Claude subscription. Although it never gets old watching the hilarity of seeing people try to and fail dramatically because, ya’know, distributed systems are hard. But a lot of the problems that come with large scale systems &lt;em&gt;don’t&lt;/em&gt; apply when your application is small, has 10 users who access it intermittently.&lt;/p&gt;
&lt;p&gt;I’d still consider myself an AI skeptic, but equally, I’m not afraid to go all in on the tools if I think the outputs can add value to people’s live.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>The Importance Of Arguing Against Yourself!</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-20-argue-against-yourself/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-20-argue-against-yourself/</guid><description>We all hold opinions, it&apos;s part of human nature. We hold these opinions as part of our identity. But other people, probably hold different opinions and conflict arises when they clash. But what if, instead of conflict, there was curioisty? How would that change things.</description><pubDate>Mon, 20 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;I never disagree with someone else’s opinion unless I understand their side better than they do – Charlie Munger&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We all hold opinions; it’s part of human nature. We hold these opinions as part of our identity. But other people hold different opinions, and conflict arises when they clash. But what if, instead of conflict, there was curiosity? Instead of shooting people down or convincing them otherwise, what if you sought understanding? People don’t just dream up their opinions; they have reasons for believing what they believe. Your job is to understand it.&lt;/p&gt;
&lt;p&gt;Sometimes I run thought experiments in my head about how the world would look if certain nuggets of wisdom were the norm. This one is powerful. Imagine a world where for every opinion someone held, they understood the opposite viewpoint better. Imagine a world where people didn’t disagree until they were sure they had full understanding. It’s an oversimplification of all the world’s problems into this simple act of understanding, but I’m confident it would help.&lt;/p&gt;
&lt;p&gt;The ‘normal’ way to tackle differing opinions is to show why you are right. “The other person is stupid because they don’t understand what I’m saying; therefore, I must shout louder”. A successful outcome is “I’m right and you’re wrong” instead of “we both learned something and moved forward”. One of the most demotivating things that can happen is to feel you’re not being listened to, yet this is all this line of reasoning does.&lt;/p&gt;
&lt;p&gt;Instead, seek to understand. Approach a differing of opinion with curiosity. Let’s follow this through with a tangible example, and not to get too political with my writing, it’s just a great example. Many of you reading will have a political affiliation. Left, right, center? I don’t care for the specifics. Whichever way you lean, though, ask yourself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;What are the reasons for not supporting them?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do you understand why you support them?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do you support them because it’s what you believe, or because you saw an inflammatory, algorithmically vomited video on social media?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Politics is a pretty inflammatory topic, but you can apply this same thinking anywhere. In your relationships, maybe your spouse/parent/sibling wants to do something one way, and you think it would work better in a different way. Don’t defend your path. Try to understand why they think their way will work. It will surprise you how often you are wrong!&lt;/p&gt;
&lt;p&gt;It’s a tricky thing to do, but if you can optimise for curiosity and understanding, believe me, your personal relationships will be better for it. And whilst it might not solve all the world’s problems, you can do your bit to make the world a more understanding place.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>How To Guarantee You Don&apos;t Miss Things When The Pressure Is On?</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-17-checklists/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-17-checklists/</guid><description>What the lowly checklist can teach you about getting things done, being more productive, and avoiding mistakes.</description><pubDate>Fri, 17 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;No wise pilot, no matter how great his talent and experience, fails to use his checklist. - Charlie Munger&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Pilots deal with a lot of pressure. Imagine having sole responsibility for a few hundred people; one mistake from you and it’s a disaster. Oh, and the thing you’re controlling, that all these people depend on, is a highly complex piece of machinery with lots of moving parts and things that could change. Dealing with a complex system, pilots prioritize checklists to make sure they never miss anything. Pilots do this when things are going well, but also when they are under pressure. Pre-take off, run the checklist. After landing, run a checklist. Something goes wrong in the air, take out the manual and run the checklist. Preparing the checklist when you aren’t under pressure, when you can think rationally, allows you to run it without thinking when things are going badly.&lt;/p&gt;
&lt;p&gt;Life is a pretty complex thing. It comes with pressures, challenges, good times, and hard times. You might not be responsible for a few hundred people, but you are certainly responsible for yourself. The lowly checklist can teach you to be more productive, avoid mistakes, and deal with pressure. For many of you, this will sound like a chore, not something that is useful. “I’ve done thing X a hundred times before, why do I need a checklist?”. Doing the same thing repeatedly, eventually you’ll get complacent. You’ll skip steps. You’ll miss things. Sometimes when you miss things, it might be ok, until the one time it isn’t.&lt;/p&gt;
&lt;p&gt;In the past, I’ve talked about &lt;a href=&quot;https://blog.jameseastham.co.uk/blog/2026/2026-07-14-second-order-thinking/&quot;&gt;second-order thinking&lt;/a&gt;. It’s dangerous if you make decisions without thinking about the downstream affects. I said in that post that I struggle myself to apply this sometimes. So why not formalise it? That’s what checklists are for. Every time you have a major decision to make, run the checklists.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Have I considered the downstream impact of this decision?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What happens if I get &lt;a href=&quot;https://blog.jameseastham.co.uk/blog/2026/2026-07-15-everyone-has-a-plan/&quot;&gt;punched in the face&lt;/a&gt;?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Have I considered the entire system and the dependencies of this decision?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You have the list ready, and you run it without thinking. Now you don’t have to remember to think about the downstream impact, you take the run book and then just run it.&lt;/p&gt;
&lt;p&gt;There is obviously some ceremony involved. In some cases, it’s not worth it. Jeff Bezos’ famous one-way and two-way doors works. If you aren’t familiar, a two-way door is an easily reversible decision. A one-way door is the opposite. For two-way door decisions, speed can matter more than considering all your options. If it doesn’t work, you reverse it. With a one-way doors though, you need to ask these kinds of questions. Run your checklist, ensure you’ve thought about the options.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Becoming Antifragile</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-16-becoming-antifragile/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-16-becoming-antifragile/</guid><description>How can the ideas of antifragiligy help you become more resilient, in all aspects of your life?</description><pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;When the variety or complexity of the environment exceeds the capacity of a system (natural or artificial) the environment will dominate and ultimately destroy that system. - Ross Ashby&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Just because something is great today doesn’t mean it will be great tomorrow. It’s not always the best idea that wins, but often the one that can best deal with change. From natural selection to the big companies of old, who over time descend into obscurity. But what is it that allows something or someone to continue to be great? The things that go beyond great are anti-fragile.&lt;/p&gt;
&lt;p&gt;Anti-fragility is a concept I first read about in Nassim Taleb’s book of the same name (the same Taleb who wrote &lt;a href=&quot;https://blog.jameseastham.co.uk/blog/2026/2026-07-12-black-swans/&quot;&gt;Black Swan&lt;/a&gt;). In the opening part of the book, Taleb describes anti-fragility as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some things benefit from shocks; they thrive and grow when exposed to volatility, randomness, disorder, and stressors, and love adventure, risk, and uncertainty. Yet, in spite of the ubiquity of the phenomenon, there is no word for the exact opposite of fragile. Let us call it anti-fragile. Anti-fragility is beyond resilience or robustness. The resilient resists shocks and stays the same; the anti-fragile gets better.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is where the opening quote of this post comes in: being able to deal with the complexity of the environment you operate within. Job one is to deal with change. To be resilient. You can’t gain from disorder if you can’t even survive it. Many of you reading this will operate in a complex environment, accepting that the world around you is constantly changing and unpredictable. You can have the &lt;a href=&quot;https://blog.jameseastham.co.uk/blog/2026/2026-07-15-everyone-has-a-plan/&quot;&gt;best plan in the world, and then you get punched in the face&lt;/a&gt;. But how do you actually become anti-fragile?&lt;/p&gt;
&lt;p&gt;I believe there are two ways, from two different areas. The first is from Taleb himself, and the idea of the barbell. The barbell strategy pairs extreme safety with extreme risk-taking, evading moderate “middle” positions. Reid Hoffman, of Netflix fame, advocates for this under a different name with his ABZ strategy. Plan A is the core pursuit, and Plan Z is the safe fallback. Applying this to investments, your plan A is a relatively ‘safe’ investment. Something that you’d be confident in, say, bonds. Then the extreme risk-taking might be something like a leveraged ETF or a crypto investment. Something with a potentially huge upside, and because you only invest a small percentage of your wealth, you minimise your risk.&lt;/p&gt;
&lt;p&gt;The second is Barry O’Reily’s idea of residuality. Particularly the idea of stressing the system. Barry comes from a software architecture perspective, but you can apply it anywhere. Say you’ve made your investment decision, you can stress that decision against a variety of different factors. What happens if the stock market crashes? What happens if the economy slows down? What happens if aliens descend upon Earth and take over the world? You can apply the stressor and then look at what the potential solution would be. This doesn’t necessarily mean you solve for every solution, but at least you understand the risks.&lt;/p&gt;
&lt;p&gt;This is important for risks that are more systematic. &lt;a href=&quot;https://www.theguardian.com/commentisfree/2025/mar/16/britain-food-supply-donald-trump-stockpile&quot;&gt;The global food system&lt;/a&gt;, the global financial system, energy supply, etc. Stress testing your current approach against this can help you understand how you can prepare. Investing in solar power, battery storage, and an electric car might seem like an enormous investment. But in a not impossible future where the climate is unpredictable, rolling blackouts become normal, or a wannabe dictator decides on a whim that affects the global fossil fuel supply, having guaranteed self-sufficiency seems less expensive.&lt;/p&gt;
&lt;p&gt;Think about anti-fragility, think about if you’re ready to deal with the complexity and unpredictability of the world around you. You won’t catch all the things that could go wrong, and you might not solve it all. But at least you are aware.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>What happens to your plans when you are punched in the face?</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-15-everyone-has-a-plan/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-15-everyone-has-a-plan/</guid><description>Everyone has plans, for life, for work. And if the plan works exactly as you expect, then great. But honestly, it&apos;s probably more important to plan what happens when things go wrong.</description><pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Everyone has a plan, until they get punched in the face. - Mike Tyson&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Golf is known as a game of misses. What separates the best players isn’t necessarily their best shots. It’s the quality of their worst shots. When I hear &lt;a href=&quot;https://www.youtube.com/shorts/7PDr_iZkkbs&quot;&gt;Rory McIlroy hit a bad shot and shout “I’m so bad at golf”&lt;/a&gt; I look at my last round and wish that I had his bad shot. When you’re playing golf, though, often when picking a target you’ll look at what’s my ‘best miss’.&lt;/p&gt;
&lt;p&gt;Imagine you’re standing behind a golf ball, needing to hit a shot. For this thought experiment, imagine you can actually strike a golf ball. There is a lake on the left and a couple of deep bunkers in front. The ‘best miss’ here is long and/or right. Obviously, the intention is still to hit the ball to the green. But knowing the best miss will help you select a better target. You might pick a club based on the distance to the back of green rather than the middle (doesn’t matter &lt;em&gt;too much&lt;/em&gt; if you go long) and when you line up the shot you’re going to pick a spot somewhere on the right side. Take the bunkers out of play, take the water out of play, and hey you might still get the ball on the green. But if you &lt;em&gt;don’t&lt;/em&gt; I’ll still be ok.&lt;/p&gt;
&lt;p&gt;I don’t know about all of you, but often when facing a decision or planning my next few months of work, I think about the happy path. When I started playing golf again, I’d always aim for the the flag. Back when I was spending more time designing systems and writing code, rather than teaching people about those things, I’d design a system based on what the expected good state looks like. For anyone who has worked in software, or made plans, this is a terrible idea.&lt;/p&gt;
&lt;p&gt;This idea of the &lt;em&gt;best miss&lt;/em&gt; is useful for life. That’s not to say you don’t want or expect the happy path, not at all. That is still the goal, still the desired outcome. But spend time thinking about where you want to miss. If you’re designing a software system, your &lt;em&gt;best miss&lt;/em&gt; is that your users still have a good experience even if everything behind the scenes is on fire. If you’re budgeting, your &lt;em&gt;best miss&lt;/em&gt; is that you have a bit of space every month for if an unexpected expense comes up. If you’re writing up a strategy for your next 6 months of work, your &lt;em&gt;best miss&lt;/em&gt; is to consider what happens if things don’t work out as expected and plan for it.&lt;/p&gt;
&lt;p&gt;If, in life, you could strive to be like an elite golfer. Where your bad shot is still 10x better than the average Joe, over time you’ve got an excellent chance of reaching your goals. Whatever they may be.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>What Are The Impacts Of Your Decisions? And Then What?</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-14-second-order-thinking/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-14-second-order-thinking/</guid><description>We spend our lives making decisions. In work, in our lives. Often, the first order impacts are quite clear. But what about the second order impacts? What about the things that are caused by the things that happen from the decision you make? Easy to miss.</description><pubDate>Tue, 14 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;When a measure becomes a target, it ceases to be a good measure - Goodhart’s Law&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I first came across the idea of Goodhart’s Law when I was working at AWS. The story I was told, which I’ve since learned has no proof, is that when the British Empire was occupying India. The local cobra population was getting too big. The British wanted to control the numbers. They offered locals reimbursement for each cobra head the locals brought in.&lt;/p&gt;
&lt;p&gt;The Brits, thinking they were smart, assumed this would cause the cobra population to shrink as they encouraged the locals to kill cobras. Some enterprising local Indians then proceeded to breed cobras, knowing they could breed them in large numbers, kill them and make a tonne of money from the stupid British. Ethics aside, what the Brits didn’t consider was the second order impact of their decision.&lt;/p&gt;
&lt;p&gt;I’ve missed these impacts several times in my career. Choosing to build microservices for a startup with a development team of 1 (me). Fun initially, 6 months later trying to lockstep releases across 4 different codebases… not so fun. Taking on a project I wasn’t that interested in but knew it would be good for my promotion, not thinking about the second order impact of “oh shit, that’s going to take up basically all of my free time for 3 months”.&lt;/p&gt;
&lt;p&gt;It’s a simple thing to challenge. Ask yourself, “and then what?”. If you’re making your decision within a complex system, you still might not catch every possible second order effect. But at least you are questioning it. Some of Barry O’Reily’s work on residuality, particularly around stressors, is relevant here. If you’re thinking about an architecture for a system, think about the possible stressors that could impact it. There are no bad ideas. Throw them all into the pot. What are the things that could happen that will cause stress on the system?&lt;/p&gt;
&lt;p&gt;Once you’ve got your list of stressors, you can then apply that to your decision. You might not solve all the problems, you might accept some of the risk. But at least you’ve acknowledged them. You’ve acknowledged that your decision might not perfect, but it’s the best you have right now.&lt;/p&gt;
&lt;p&gt;If you layer these second order impacts into a fictional person who goes all in on AI, let’s call them Karl. Karl has spent the last 12 months using AI for everything. He’s basically automated his entire job away. He uses it for coding, for note-taking, for summarising his notes, for sending his emails, managing his inbox and calendar. Karl feels great because he’s got an AI to automate away his entire job. Now he can just play golf and get paid for it. The first order impacts are overwhelmingly positive.&lt;/p&gt;
&lt;p&gt;Let’s stress this decision. What if, as many people predict, the per-token cost of using LLM’s skyrockets. &lt;a href=&quot;https://www.wheresyoured.at/exclusive-openai-financials/&quot;&gt;AI providers have got to get out of their 32 billion dollar losses somehow&lt;/a&gt;. With an X number of times cost. Is it still viable? Karl has offloaded his ability to think to a hallucinogenic &lt;a href=&quot;https://www.experimental-history.com/p/bag-of-words-have-mercy-on-us&quot;&gt;bag of words&lt;/a&gt;. Maybe the only way he can move forward is to pay the LLM companies. Bad for Karl, great for OpenAI.&lt;/p&gt;
&lt;p&gt;An alternative stressor is that his employer realises Karl has just proved AI can automate away his entire job. Great for the employer, they fire Karl and keep his automations. Karl is sad. But at least he has time to play golf now? For the AI company, though, they now need to consider the aforementioned stressor because what if token costs go up X amount because someone needs to find 32 billion dollars somewhere.&lt;/p&gt;
&lt;p&gt;Now Karl’s company is wishing they had Karl back.&lt;/p&gt;
&lt;p&gt;There are a lot of if’s and but’s in that short narrative. The point doesn’t have to be that you &lt;strong&gt;believe&lt;/strong&gt; something will happen. The point is to go wild and consider all possible outcomes. Maybe Karl decides he is happy with both of those risks and he carries on. Cool. But at least you’ve considered the longer tail of impacts.&lt;/p&gt;
&lt;p&gt;Ask yourself, “and then what?”. And start to consider the second order impacts.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>You&apos;re A Human, You Can Do It!</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-12-if-they-can-do-it/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-12-if-they-can-do-it/</guid><description>We are all humans, and we can all do things. If there&apos;s another human on the planet who can do something, it means you can do it too. We all have the same bodies.</description><pubDate>Mon, 13 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;“Do not think that what is hard for you to master is humanly impossible; and if it is humanly possible, consider it to be within your reach.” ― Marcus Aurelius, Meditations&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A few years ago, I was running ultra-marathons. 26-mile plus running races, with the furthest I competed in being 50 miles. There were a lot of reasons I started running ultra-marathons, which I won’t go into here. What I didn’t expect was the number of life lessons I took away. One of my favourites comes from Stoic philosophy.&lt;/p&gt;
&lt;p&gt;Paraphrasing Marcus Aurelius, “If a human can do it, and you yourself are a human, then you can do it too.”. If there are examples of a human performing a task, given you are also a human, then it is within your grasp. It goes without saying, there are limits to this statement. I’m not going to will myself into being the next Usain Bolt. There are &lt;em&gt;some&lt;/em&gt; biological limitations. When you look around at almost any human endeavour there are people of all different backgrounds and abilities. If they can do it, and they are human, then why can’t I?&lt;/p&gt;
&lt;p&gt;I find this incredibly motivating, and it feeds the work by Carol Dweck on growth mindset. Simplifying Carol’s work, there are two types of mindsets: fixed and growth. A fixed mindset is one that believes you can’t improve, and a growth mindset is one that believes you can. I can look at Usain Bolt and say a) I’m never going to be as fast as him, why would I try or b) I’m going to train hard and get as fast as I can. If he can do it, why can’t I?&lt;/p&gt;
&lt;p&gt;One thing that separates some of the hardest working, talented people I know from some incredible people who don’t seem to move ‘forward’. Do you look at the world and think everyone is better than me why bother trying? Or do you look around and think all these other people are human just like me, I’m going to push and become the best that I can be. This mindset has served me well, but it’s worth noting that not everyone starts from the same place.&lt;/p&gt;
&lt;p&gt;It’s important to apply this thinking to things &lt;a href=&quot;https://blog.jameseastham.co.uk/blog/2026/2026-07-09-golf-and-control/&quot;&gt;within your control&lt;/a&gt;, things outside your control are just that. Of course, societal barriers and discrimination are real, and not everything is within our control. But where you do have agency, this mindset can help push you forward. Remember, if it is humanly possible, it’s within your reach.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>What Can Swans Teach You About Making Better Decisions?</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-12-black-swans/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-12-black-swans/</guid><description>Swans, a stunning animal seen in the wild. But what can the swan teach you about making better decisions, in software and in life? Let&apos;s find out with Nassim Taleb</description><pubDate>Sun, 12 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have just finished re-reading (I think for the 3rd time now) ‘The Black Swan: The Impact of the Highly Improbable’ by Nassim Taleb. It’s a dense read, but if you need to make decisions in unpredictable arenas, then it’s well worth picking up. Oh, wait… Making decisions in unpredictable arenas? That’s all of you. It’s called life.&lt;/p&gt;
&lt;p&gt;A Black Swan is a completely unpredictable event that has outsized consequences. Human history is made up of these big unpredictable events that nobody saw coming. Things like the 2008 financial crisis, 9/11, along with many other events throughout history. It can even be something you predict but under-or overestimate the impact. You launch a startup expecting 1,000 users, and you go viral and get a 1,000,000.&lt;/p&gt;
&lt;p&gt;If you are working in a domain that is unpredictable, and where the outcome has big consequences. You have to be aware of the Black Swans. Part of the problem is that we humans aren’t great at being ready for them. We love stories. We look back at an event, assign a narrative, and use that to rationalize why something happened. This gets dangerous when we use that to project forward. We think we are “learning” from history. But if you are dealing with something complex, there is no guarantee the future will be anything like the past. In fact, it’s probably the opposite.&lt;/p&gt;
&lt;p&gt;What does this mean for you? First off, beware the expert. If somebody calls themselves an “expert” in a domain that is based on prediction, is complex with variability, then believe nothing they say. You can see that in real time with AI. It seems everyone has become an “expert” in AI and knows what the future is going to be. In reality, nobody knows anything. Without real, hard, empirical facts, all you have is speculation. If the “expert” omits the potential variability in their prediction, trust them even less.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An important aside, you should definitely trust the experts in domains that are more static. Doctors, surgeons, etc… If the domain &lt;strong&gt;isn’t&lt;/strong&gt; unpredictable, trust them. Human brains are pretty static.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once you become skeptical of experts, you can make more pragmatic decisions about your day-to-day life. You can take the views of ‘experts’, look at the variability in outcomes and use that variability to decide your approach. Look at the positive and negative potential outcomes, and ensure you are prepared both. The Stoic idea of premeditatio malorum feeds into this. What’s the worst thing that could happen, prepare for it.&lt;/p&gt;
&lt;p&gt;You might not change, you might even carry on as if the positive outcome is going to happen. Being prepared for the worst makes it less of a shock if it does happen, though.&lt;/p&gt;
&lt;p&gt;Expect much more from The Black Swan over the coming weeks.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>What If Today Was The Last Time You Got To Do Your Favourite Thing?</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-11-momento-mori/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-11-momento-mori/</guid><description>The Stoic idea of Memento Mori and how it&apos;s less pessimistic than you might think, allowing you to improve your enjoyment of every moment in life.</description><pubDate>Sat, 11 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;You could leave life right now. Let that determine what you do and say and think. - Marcus Aurelius, Meditations&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Memento mori - Remember you are going to die. Bit of a pessimistic thing to open with on a Saturday, I’ll grant you that. But the idea of memento mori is one of the most misunderstood pieces of Stoic philosophy and is more widely applicable than just making you question your own mortality.&lt;/p&gt;
&lt;p&gt;In Meditations, Marcus Aurelius writes, “You could leave life right now. Let that determine what you do and say and think”. Taken at face value, it’s the grim thought that you are going to die. Underneath that is a deep appreciation for the things you do every day. Everything you do in your life, at some point you are going to do it for the last time. Eat pizza, go for a walk, play golf, go out for a run, give your parents/partner/sibling a hug. The cruel part is that you never know &lt;strong&gt;when&lt;/strong&gt; the last time is going to be.&lt;/p&gt;
&lt;p&gt;When you apply this every day, though, it is genuinely life-changing (and I don’t use that word lightly). The impermanence of everything around you increases your appreciation of it. This might be the last time you get to eat pizza; savour every single bite. This might be the last time you can hug your partner, squeeze them extra tight. You just never know.&lt;/p&gt;
&lt;p&gt;Next time you do something you enjoy, remember it might be the last time you get to do it. Don’t get sad about it, appreciate it. Enjoy it. Savour it.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>You Must Not Forget About The Entire System</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-10-systems-thinking/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-10-systems-thinking/</guid><description>The importance of understanding the entire system when making decisions, and how the way we are taught to think in school causes more problems than it solves.</description><pubDate>Fri, 10 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;‘You think that because you understand “one”, that you must therefore understand “two” because one and one make two. But you forget, that you must also understand “and”’ - Donella Meadows, Thinking in Systems&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;How do think? It’s not something you probably think about very often. You’re born, you go to school, you learn some stuff, you go to work, where you hopefully use the things you’ve learned to think about a problem. At least in Western culture, most things we are taught follow a model of linear thinking. The school year has a sequence, every lesson has a sequence. A and then B and then C and then D.&lt;/p&gt;
&lt;p&gt;This is great for a lot of things. Passing exams in school, at least with the way most school systems work, requires this style of thinking. With the chaos of the modern world, there’s another type of thinking I’d argue is more important. It starts with the child asking “why”.&lt;/p&gt;
&lt;p&gt;If you’ve spent any amount of time around a child, they are constantly asking why. Why is this like this? How does X relate to Y? What caused that to happen? It’s cute from the outside, as someone who’s about to become a father for the first time, ask me if it’s still cute in a few years. The child is trying to make connections. To work out how the different pieces of their understanding and how they relate to each other. The child, quite naturally, is thinking in systems.&lt;/p&gt;
&lt;p&gt;Somewhere along the way, this gets lost. Linear thinking is pushed down your throat, learn this, then this, then this. You get a job, perform task X, then task Y, then task Z, and hopefully at the end get a pay rise. When you’re down in the detail this works well, but the world around us isn’t linear and definitely doesn’t follow a straight, easy to understand path.&lt;/p&gt;
&lt;p&gt;Imagine for a moment you had to make a decision about the future of the company you work for. For arguments sake assume you work in finance. One way to make the decision is to simply make the best decision that benefits &lt;strong&gt;you&lt;/strong&gt;, right now. The selfish option. And honestly, I’ve seen lots of people over the years who take this approach. But the company is made up of lots of different people, departments, customers, suppliers. There is an entire complex web of relationships that make up the system as a whole. To make something like a sensible decision, you need to have some understanding of the entire system. If you were to apply linear thinking to this task, you might think the best decision (for accounts) is to put up your prices 100x and find a cheaper supplier. $$$ for everyone! The short-term impact - profits go up and you look great for your insightful decision. But what’s the long-term impact of your decision? If you’ve forgotten about the rest of the system (in this case, customer satisfaction) your system is going to die.&lt;/p&gt;
&lt;p&gt;Systems thinking is about trying to understand all the nodes, all the relationships, and how they work together to make the system as a whole. Famous system thinker Russel Ackoff said “A system is never the sum of it’s parts - it’s the product of their interaction”. When it comes to making decisions, think about the different pieces but more importantly think about their interactions. If you understand one piece, ask yourself what are the other pieces that I interact with and if I make change X how is that going to impact them. It’s not about slowing down, it’s about truly understanding the long term impacts of your actions.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Golf &amp; The Dichotomy of Control</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-09-golf-and-control/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-09-golf-and-control/</guid><description>Life lessons from playing golf</description><pubDate>Thu, 09 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently I have started playing golf again. I used to play when I was younger, and after a 15 year hiatus I decided to start swinging a club again. For anyone reading who hasn’t played golf before, what you won’t realise is that golf is a sport in which you spend 50% of your time thinking it’s the greatest game ever, and the other 50% asking why some folks in Scotland decided it was a good idea to try and hit a tiny white ball 400 yards into a tiny little hole.&lt;/p&gt;
&lt;p&gt;Practicalities of golf aside, the other thing I love about the sport is that it teaches you &lt;em&gt;SO MANY&lt;/em&gt; life lessons. The venn diagram of things that cause problems in golf and things that cause problems in real life has a pretty decent cross over. One of my favourite, is about controlling the controllables and the false level of control that golf, and life, gives you.&lt;/p&gt;
&lt;p&gt;In golf, all you can control is your own process. Just this morning, I hit one of my best shots of the round. The feeling off the tee, the flight of the ball through the air. Then it takes a crappy bounce and somehow ends up in a bunker (a big hole filled with sand for the uninitiated). I’d got everything right. The pre-shot, the target, the setup, the swing. And still, the outcome wasn’t the outcome that I hoped for.&lt;/p&gt;
&lt;p&gt;I’m sure reading that, many of you can relate that to things that have happened in your life. You got everything right, and the outcome wasn’t the outcome you wanted. This is where, sometimes, the game of golf can start to differ from life though. I’m slowly realising that golf is 80% mental. Yes, you might physically swing a club but it’s what between your ears that has a huge impact on how you play.&lt;/p&gt;
&lt;p&gt;In a round of golf, it’s tough shit. You have two options here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Complain about being in the bunker, and the tricky shot you’ve got out of the sand. Get yourself in a mental tangle and beat yourself up OR&lt;/li&gt;
&lt;li&gt;Understand that you got everything right. Your setup, your swing, your strike - everything was perfect. Just not the outcome you wanted.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Replace the world golf and bunker with life and challenge, and you can see that the dichotomy of control applies to life in the same way. Day to day, all you can control is yourself. As much as you might like to think otherwise, the only thing you have real agency over is yourself and your decisions. Everything else is out of your control. So be ready for it.&lt;/p&gt;
&lt;p&gt;When things don’t go your way, ask yourself did I do everything in &lt;strong&gt;my power&lt;/strong&gt;? Was I the best I can be? If you consistently answer yes to that question, I promise you the outcome will take care of itself.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Best Practices Can Be The Worst Decisions</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-08-best-practices/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-08-best-practices/</guid><description>Choosing a &apos;best practice&apos;, what could possibly go wrong?</description><pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The world is full of ‘best practices’. Things that are accepted as always being the ‘right’ way to do things across a range of different industries. And yes, whilst there are things that might nudge you in the right direction, blindly following something because everyone else is doing it misses a lot of nuance.&lt;/p&gt;
&lt;p&gt;Before I joined AWS I did quite a bit of freelance software development, mostly with startups. At the time, I had mostly been building monolithic .NET applications (and a bit of SQL Server DBA-ing) and had started to hear about this thing called microservices. The startup I was working with at the time had reasonably good domain boundaries, and pretty obvious splits in the functionality. “What an excellent opportunity to take on this current industry best practice” I thought.&lt;/p&gt;
&lt;p&gt;It was not!&lt;/p&gt;
&lt;p&gt;Because yes, microservices are a good way of building software. Smaller units that run independently and are easier to understand. In principle, it sounds great. What is often missed when talking about microservices though, is the wider system. What is the environment like around the software, and how does that impact your decisions. This is what I missed.&lt;/p&gt;
&lt;p&gt;Because at the time, I was in a development team of 1. Me. And the startup was also pivoting as the needs of it’s customers changed. What was a logical split today, caused pain later as two domains ended up needing to be smashed back together.&lt;/p&gt;
&lt;p&gt;Ross Ashby was a psychologist and cyberneticist, and he stated “if the complexity of the environment exceeds the systems capacity to respond, the environment will always win and the system will die”. You see this play out in the natural world. The climate is changing rapidly, ecosystems can’t respond, the ecosystem dies.&lt;/p&gt;
&lt;p&gt;Initially, you might think microservices allow you to respond to a changing environment more quickly. And yes, in some cases, they might. In many cases, they won’t. Here, the changing environment led to domains completely changing. Pieces of functionality disappearing, new ones appearing, and some joining together. Having independent codebases, independent deployments, and independent functionality hindered the system’s ability to respond.&lt;/p&gt;
&lt;p&gt;That’s not to say microservices are bad. Not at all. The important thing to remember is to always think about the second order impacts of your decisions. What changes could happen later and how might that affect my decision today?&lt;/p&gt;
&lt;p&gt;There’s probably a lesson for life in there as well.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Why I&apos;m Writing More, And Actually Writing</title><link>https://blog.jameseastham.co.uk/blog/2026/2026-07-07-30-in-30/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026/2026-07-07-30-in-30/</guid><description>Why I&apos;m choosing to write more, and actually writing the whole thing myself</description><pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I tried starting a blog for years, somehow it never quite caught on. I’d post intermittently for a month or two before eventually giving up. Starting a YouTube channel and creating video content scratched that itch for a while. Somehow, I just found it easier to hit record and go rather than think about what sitting down and writing.&lt;/p&gt;
&lt;p&gt;But skills that aren’t used atrophy. And with the rise of AI to basically do everything, it seemed like a good time to revisit writing. Without AI, without any help. Just me scribbling down my thoughts. For the next 30 days, I’m loosely following the &lt;a href=&quot;https://www.ship30for30.com&quot;&gt;‘Ship 30 for 30’&lt;/a&gt; approach. Writing short pieces, every day, for the next 30 days.&lt;/p&gt;
&lt;p&gt;Nobody might read it, that’s ok. Think of it as skill building, as keeping skills sharp. In much the same way I still write &lt;em&gt;some&lt;/em&gt; code, even though and LLM could generate it for me. I for one don’t fancy offloading all my thinking, or my skills, to an AI owned by a US tech company. You shouldn’t either.&lt;/p&gt;
&lt;p&gt;Topics may vary, in my head ideas bounce around about systems thinking. Stocism. Philsophy. Software Architecture. Maybe even some lessons I’ve learned from picking up golf again. It might be practical, it might be random musings about something I’ve read.&lt;/p&gt;
&lt;p&gt;The point isn’t to get a million subscribers, or become the next big things on substack. The point is to keep skills sharp, to write regularly, and to think.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Ergodicity Why Averages Lie and Systems Break</title><link>https://blog.jameseastham.co.uk/blog/2026-04-20-ergodicity/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026-04-20-ergodicity/</guid><description>Why you should care about ergodicity, how it applies to modern life and what it means for software development.</description><pubDate>Tue, 21 Apr 2026 14:02:36 GMT</pubDate><content:encoded>&lt;h1 id=&quot;ergodicity-why-averages-lie-and-systems-break&quot;&gt;Ergodicity: Why Averages Lie and Systems Break&lt;/h1&gt;
&lt;h2 id=&quot;the-migration-that-shouldnt-have-been-hard&quot;&gt;The migration that shouldn’t have been hard&lt;/h2&gt;
&lt;p&gt;Your company has always been an Azure shop. Then a decision comes down from way
above your pay grade. Your cloud provider of choice has gone out to tender. AWS
won over Azure. Now it’s come down from the top: you need to move all your
applications to AWS.&lt;/p&gt;
&lt;p&gt;You’re not worried. You’ve containerised everything with Kubernetes. Kubernetes
runs anywhere. That’s the whole point. You sit there, smugly I might add,
knowing the migration will be easy.&lt;/p&gt;
&lt;p&gt;It isn’t.&lt;/p&gt;
&lt;p&gt;Almost immediately, you realise a monumental problem. The problem isn’t
Kubernetes. That part works exactly as you expected. Stateless containers run
anywhere. The problem is CosmosDB — Azure’s proprietary database service.
CosmosDB doesn’t run on AWS.&lt;/p&gt;
&lt;p&gt;It’s embedded across multiple applications. Swapping it out means significant
application-level code changes. Not just infrastructure changes. Not the kind
of thing you can abstract away with a container orchestrator. The kind of thing
that means months of rework you hadn’t budgeted for.&lt;/p&gt;
&lt;p&gt;You’d made an assumption: &lt;em&gt;our architecture is portable across cloud providers&lt;/em&gt;.
Kubernetes gave you confidence in that assumption. But Kubernetes abstracts away
the compute layer. It doesn’t abstract away the data layer. Or any other layer.&lt;/p&gt;
&lt;p&gt;Nobody had asked the question that would have surfaced this: &lt;em&gt;“What happens if
we need to leave Azure?”&lt;/em&gt; Not because leaving Azure was likely. Just to
understand what the answer would be.&lt;/p&gt;
&lt;p&gt;You hadn’t made a technical mistake. You’d made a reasoning mistake — and it
has a name.&lt;/p&gt;
&lt;h2 id=&quot;what-ergodicity-actually-means&quot;&gt;What ergodicity actually means&lt;/h2&gt;
&lt;p&gt;Ergodicity. It sounds like something from a statistics textbook you skimmed in
university and never thought about again.&lt;/p&gt;
&lt;p&gt;A coin flip is the clean example. Send 100 people out to each flip a coin once
and you’ll get roughly 50 heads and 50 tails. Have one person flip a coin 100
times and you’ll get roughly the same. The path doesn’t matter. A run of 10
tails in a row doesn’t change the probability of the next flip. The group
average and the individual average converge.&lt;/p&gt;
&lt;p&gt;As humans, we think in averages. We apply this same reasoning to many real
world scenarios — mean time to failure, average returns, expected value. On
average, mean time to failure is 2 hours. Great. But what works for the group
doesn’t always hold for the individual. The average could be fine, but one
massive outlier can destroy you.&lt;/p&gt;
&lt;p&gt;Most of the statistical tools we reach for assume ergodicity. Most real-world
systems don’t satisfy it.&lt;/p&gt;
&lt;p&gt;That distinction — between the group average and the individual path — is what
we most often get wrong. Once you see it though, you start noticing it
everywhere.&lt;/p&gt;
&lt;p&gt;The place it’s easiest to see isn’t in software. It’s in money.&lt;/p&gt;
&lt;h2 id=&quot;the-pattern-is-everywhere&quot;&gt;The pattern is everywhere&lt;/h2&gt;
&lt;p&gt;Your production architecture has more in common with a 1966 retirement portfolio
than you might think.&lt;/p&gt;
&lt;p&gt;Say you retire and plan to draw down a fixed amount each year. You’ve done the
maths. 8% is the average historical return, so you use 5% as your number —
conservative, sensible. The numbers work. Excellent.&lt;/p&gt;
&lt;p&gt;If you retired in 1966, here’s what actually happened. Near-zero returns from
1966 to 1982. Then roughly 15% per year from 1982 to 1997. The average return
across the full period looks fine. But you were drawing down during the flat
years, before the growth arrived. By the time the good years came, there might
not be enough left in the pot to benefit from them.&lt;/p&gt;
&lt;p&gt;The group average looks healthy. It tells you nothing useful about the person
who retired in 1966. The path mattered. The sequence mattered. The average
didn’t protect you.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.investopedia.com/terms/s/sequence-risk.asp&quot;&gt;Sequence of returns risk&lt;/a&gt;
is a well-documented phenomenon. You can mitigate it. Diversified investments,
asset allocations, emergency funds, regular reviews of your portfolio.&lt;/p&gt;
&lt;p&gt;The answer isn’t to predict the future better. It’s to build in a buffer that
keeps you in the game long enough for the averages to work in your favour. A
cash reserve. Shifting some of your investments into bonds. Keeping a margin of
safety. Something that absorbs a bad sequence before it becomes fatal.&lt;/p&gt;
&lt;h2 id=&quot;back-to-software&quot;&gt;Back to software&lt;/h2&gt;
&lt;p&gt;So back to you, your Azure shop, and CosmosDB.&lt;/p&gt;
&lt;p&gt;The ergodic assumption the team had made was reasonable on the surface: &lt;em&gt;because
we chose to use Kubernetes, we built portability as a first-class citizen&lt;/em&gt;. In
an ergodic system that would hold. The path — which cloud you’re on — wouldn’t
matter, because the architecture behaves the same regardless.&lt;/p&gt;
&lt;p&gt;But the system was non-ergodic. The path had locked you in. CosmosDB was
embedded in ways Kubernetes couldn’t abstract away. Nobody thought to ask what
a migration would cost until it was already underway.&lt;/p&gt;
&lt;p&gt;The question that should have been asked wasn’t “are we likely to leave Azure?”
It was “what would it take if we did?” The answer would have surfaced the
dependency. It might not have changed the decision to use CosmosDB. But wrapping
it behind an interface would have made it a contained change, not a
codebase-wide rework.&lt;/p&gt;
&lt;p&gt;Migrating from CosmosDB to an AWS-managed database isn’t easy — it definitely
isn’t. But at least the changes stay in the codebase.&lt;/p&gt;
&lt;p&gt;That’s one side of it. What about when it goes well?&lt;/p&gt;
&lt;p&gt;A team builds a system for roughly 100 active users. They choose a serverless
architecture — partly for cost, partly for simplicity. The system grows. 10,000
users. Then 20,000. And because of the serverless foundation, it scales
elastically.&lt;/p&gt;
&lt;p&gt;Here’s the honest version of that story though: the resilience was accidental.
The team didn’t sit down and reason explicitly about ergodicity or future states.
They got lucky. The early architectural choice happened to be path-independent
in exactly the right way.&lt;/p&gt;
&lt;p&gt;Whilst you can get the right answer without thinking formally about ergodicity,
you’re playing a luck game. Sometimes you might come good. If you were the
investor from 1982 to 1997 you’d think you were a genius. You just happened to
be in the right place at the right time.&lt;/p&gt;
&lt;p&gt;Using ergodicity as a lens gives you a deliberate path to better outcomes.
Instead of hoping your early choices happen to age well, you ask the question
upfront: am I locking in a path here? What does this system look like if usage
grows by 100x? What does it look like if we need to change providers? What does
it look like if we discover Godzilla is real, and he comes storming out of the
sea and stomps all over us-east-1.&lt;/p&gt;
&lt;p&gt;This isn’t about predicting every possible future. It’s about knowing where
your path dependencies live before they surface in an emergency.&lt;/p&gt;
&lt;h2 id=&quot;the-intellectual-lineage&quot;&gt;The intellectual lineage&lt;/h2&gt;
&lt;p&gt;This isn’t a new idea. It’s been formalised — and that formalisation matters.&lt;/p&gt;
&lt;p&gt;Barry O’Reilly’s work in Residuality Theory overlaps closely with this framing.
I’d read both of his books — Residuality Theory and The Architect’s Paradox —
and understood the ideas. But a specific post O’Reilly made on LinkedIn —
explicitly connecting ergodicity to software architecture — made the concept
click.&lt;/p&gt;
&lt;p&gt;The central move in Residuality Theory is this: map the possible future states
of a system, not just the expected state. Ask “what if…” systematically rather
than optimising only for the happy path. Instead of asking “will my architecture
handle the average case?”, ask “what does my architecture look like across the
distribution of possible futures?”&lt;/p&gt;
&lt;p&gt;If you want to go deeper, Barry’s work is the place to start.&lt;/p&gt;
&lt;p&gt;Which brings it down to a single question you can ask before any design
decision.&lt;/p&gt;
&lt;h2 id=&quot;one-question&quot;&gt;One question&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Have I thought about whether my architecture has hidden dependencies that would
make future changes expensive?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That is the question.&lt;/p&gt;
&lt;p&gt;The follow-up is just as useful: &lt;em&gt;how will this system evolve over time, and
have I thought through the possible future states?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The CosmosDB team didn’t need to predict the contract change. They needed to
know that CosmosDB was a path dependency — so that if a migration was ever
required, it wasn’t a surprise. The serverless team got lucky. Asking the
question deliberately means you don’t have to rely on luck.&lt;/p&gt;
&lt;p&gt;The goal isn’t to solve every potential future problem upfront. It’s knowing
where the constraints live. Where the assumptions are baked in. Where a path
dependency could cost you months when the future diverges from the average. Ask
the questions, briefly capture the answers. A paragraph in a decision log, a
note in the ADR (architecture decision record) and work from there. You need a
record the question was asked and what the answer was at the time.&lt;/p&gt;
&lt;p&gt;Most of the time the answer will be “this is fine.” But occasionally you’ll
catch something. And when you do, it’s far more valuable than discovering it
three months into a full codebase refactor.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Design Thinking and the Question Serverless Should Be Asking</title><link>https://blog.jameseastham.co.uk/blog/2026-04-12-design-thinking/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026-04-12-design-thinking/</guid><description>Applying design thinking principles to serverless adoption starting with the human-centred questions that actually matter.</description><pubDate>Sun, 12 Apr 2026 10:58:36 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;“At the heart of any good story is a central narrative about the way an idea satisfies a need in some powerful way.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;“What’s the story of serverless?” What need does it satisfy?” Not the technical need. The human need. Why does it resonate so well with some people and not so well with others?&lt;/p&gt;
&lt;p&gt;I believe that serverless is the #1 way for anyone to get started building something new. Whether you believe the hype or the haters, it is irrefutable that if you have an idea and you want to get it in front of users as quickly as possible, serverless is the way. &lt;em&gt;By using the word serverless here, I am referring to all managed services, including things like Azure Container Apps, Amazon ECS/Fargate, Google Cloud Run, not just functions&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When most people talk about serverless, me included, they lead with the technical stuff. No servers to manage. Pay per invocation. Auto-scaling. All true, all useful. But none of that is a story. The emotional connection just isn’t there.&lt;/p&gt;
&lt;h2 id=&quot;maybe-the-story-is-wrong&quot;&gt;Maybe the Story Is Wrong?&lt;/h2&gt;
&lt;p&gt;Design thinking has this concept of always starting with a human-centred question. Not “how do we build a better voting machine,” but “how might we enhance the democratic experience.” The focus shifts from the noun to the verb. From the thing to the feeling.&lt;/p&gt;
&lt;p&gt;So what does that look like for serverless?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;How might we help someone ship their brand new idea in a way that minimises personal risk?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How might we enable anyone, anywhere, to bring their idea to life?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How might we help developers prototype and pivot without getting bogged down in infrastructure?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those questions feel very different to “how to run your app in a way that means it will scale automatically, and mean you don’t need to care about servers”. We are all humans talking to other humans, and as humans we love stories.&lt;/p&gt;
&lt;p&gt;Homo Sapiens by Yuval Noah Harari is a book I refer to often. And one of the core ideas in that book is the importance of stories. Stories are fundamental to the success of the human species. From the obvious stories our ancestors will have told “don’t go down to the watering hold, there’s a lion that will eat you” to the not so obvious example of things like the modern financial system. The modern financial system, like many things in our lives, are built on a shared story. A shared belief. A shared idea.&lt;/p&gt;
&lt;p&gt;It’s stories and shared beliefs that allow us to operate together at massive scales. Whether it’s the financial system, the company you work for, your nationality, your religion, your political leaning or anything in between. Our ability to connect, and to share stories, is what sets us apart as a species.&lt;/p&gt;
&lt;p&gt;Yet all too often, not only in tech, we start with the technical details not the human-ness.&lt;/p&gt;
&lt;h2 id=&quot;the-container-story-is-already-written&quot;&gt;The Container Story is Already Written&lt;/h2&gt;
&lt;p&gt;Looking away from serverless for a moment, containerisation and Kubernetes in particular have a compelling story, even if it’s not always the right one.&lt;/p&gt;
&lt;p&gt;Build your application using a well-documented, well-understood web framework. Package it into a container, which everyone knows and understands. Ship it to an orchestrator that everyone in the industry says is the way to run large scale applications.&lt;/p&gt;
&lt;p&gt;Nobody got fired for buying IBM, right? And no CTO got fired for doing what everyone else is doing… Which in this case is deploying the app to Kubernetes. The &lt;em&gt;safe&lt;/em&gt; choice maps to the existing mental models which makes the story easier to tell.&lt;/p&gt;
&lt;p&gt;That’s a genuinely hard thing to compete with when you’re trying to get someone to shift their thinking toward a new paradigm. The serverless story needs to be just as easy to tell. And right now, I’m not sure it always is.&lt;/p&gt;
&lt;h2 id=&quot;prototyping-as-a-first-class-citizen&quot;&gt;Prototyping as a First-Class Citizen&lt;/h2&gt;
&lt;p&gt;One of the other ideas from design thinking that really resonated with me was this: &lt;em&gt;“A vibrant design-thinking culture will encourage prototyping — quick, cheap and dirty — as part of the creative process, not as a way of validating finished ideas.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That’s exactly what serverless should be. There is no better tool available for moving quickly. You have an idea, you write some code that focuses purely on the business logic, you deploy it, and it scales when it needs to. No infrastructure setup beforehand. No cluster to configure. Just your idea, running in the cloud.&lt;/p&gt;
&lt;p&gt;That’s a story worth telling. An early career developer who wants to learn fast. A founder with a weekend and an idea. An experienced developer who wants to prototype something without spinning up a bunch of infrastructure first. You’ve just vibe coded something into existence, now what? It certainly isn’t go and spin up an EKS cluster, provision an ingress controller and write a Helm chart.&lt;/p&gt;
&lt;p&gt;Every single one of us now has the power to go from idea -&amp;gt; working product -&amp;gt; running in production in an afternoon. The aha moment of having the app created is great, and serverless technologies allow you to productionise it. But also to do that in a way that has low financial risk whilst also being scaleable if you do happen to go viral.&lt;/p&gt;
&lt;p&gt;The fundamental starting point of most applications is a web app and an API. What does the customer journey of building and shipping a web app on serverless look like compared to doing the same thing on a container orchestrator? I think if you map those two journeys out honestly, the serverless path is significantly shorter and significantly less painful for the person just trying to get their idea in front of real users.&lt;/p&gt;
&lt;p&gt;Granted, if you have an entire platform team around you to build and run the container orchestrator for you then great. The journey to shipping the POC is probably equally as simple in that case. I once spoke with someone at a conference who said “My company uses Kubernetes, but all I do to is push a container image, the rest just happens and it scales automatically. Does that mean I’m serverless?”.&lt;/p&gt;
&lt;p&gt;Yes, yes it does my friend. Not everyone is that lucky though.&lt;/p&gt;
&lt;p&gt;To be clear, I’m not suggesting that you can’t run proof of concepts on Kubernetes. And equally, I know of hundreds of companies running large scale production workloads purely on AWS Lambda. As I’ve argued before, framing this as ‘serverless vs. containers’ misses the point. The real question is: What’s the fastest path to delivering value to users? &lt;a href=&quot;https://blog.jameseastham.co.uk/blog/on-factors-of-modern-compute/&quot;&gt;https://blog.jameseastham.co.uk/blog/on-factors-of-modern-compute/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Maybe you’re reading this an you’ve heard all about serverless. And you’ve heard the naysayers. Frankly, some of them are right. Yes, your serverless functions will have cold starts (they probably aren’t as bad as you think). Yes, you may be locked into a specific vendors managed service (thinking about code design prevents this. Kubernetes has lock in too ya’know).&lt;/p&gt;
&lt;p&gt;But if you’re trying to get &lt;strong&gt;anything&lt;/strong&gt; you build in front of actual real people, in a way that will scale alongside your business with next to 0 effort on your part, that’s a worthwhile trade off to make.&lt;/p&gt;
&lt;h2 id=&quot;shifting-the-focus-outward&quot;&gt;Shifting the Focus Outward&lt;/h2&gt;
&lt;p&gt;A lot of the conversation in the platform engineering and infrastructure space is inward-facing. How do we run our systems better? How do we manage our clusters? How do we reduce operational overhead for our internal teams?&lt;/p&gt;
&lt;p&gt;All valid questions. But design thinking pushes you to zoom out. To think about the organisation and their customers. To think about the users of the software that teams are building.&lt;/p&gt;
&lt;p&gt;What are the benefits to them? Does your user care whether their request was handled by a Lambda function or a container on a Kubernetes node? Absolutely not. They care that it was fast, reliable, and that the product keeps improving to meet their changing needs.&lt;/p&gt;
&lt;p&gt;Spending a huge amount of time and money on platform engineering is not innovating. It’s not human-centred. It’s not solving the needs of your users. There’s a version of it that enables teams to move faster, sure. But a lot of the time it’s just undifferentiated heavy lifting dressed up as strategy.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Eventually&lt;/em&gt;, maybe Kubernetes is on the horizon. If you start with a serverless function, and 18 months down the line you realise your workloads better suits a long running container then amazing. The answer still isn’t Kubernetes, but maybe you start to head down that road.&lt;/p&gt;
&lt;p&gt;At each specific moment in time you made a pragmatic architectural choice about how you want to get your application in front of users in the best possible way.&lt;/p&gt;
&lt;p&gt;It’s another reason why I think the ability to adapt your system over time as it’s needs change, is the most important consideration for any software system. Things will change, it’s inevitable. Have you designed your system to be able to deal with that change? The #1 problem I see with AI generated code is that, without careful prompting, evolvability goes out the window.&lt;/p&gt;
&lt;h2 id=&quot;a-few-practical-things-ive-taken-from-this&quot;&gt;A Few Practical Things I’ve Taken From This&lt;/h2&gt;
&lt;p&gt;Design thinking has some really simple habits that I think are worth stealing regardless of what you’re working on. Be it serverless, be it something else in tech, or not in tech at all.&lt;/p&gt;
&lt;p&gt;Stop regularly and ask yourself five whys. Why do I do this thing this way? Why has this always been the default? It’s a surprisingly effective way to challenge assumptions that have just been sitting there unchallenged.&lt;/p&gt;
&lt;p&gt;Sketch things out. Not as polished diagrams, just rough sketches. Customer journeys, system flows, the path from idea to production. Drawing forces clarity in a way that writing often doesn’t.&lt;/p&gt;
&lt;p&gt;And reframe your questions as verbs. Don’t ask how to build a better serverless platform. Ask how you might enhance a developer’s ability to quickly prototype and ship. Don’t ask how to improve adoption metrics. Ask how you might make the getting started experience so good that people just want to rave about it to their colleagues.&lt;/p&gt;
&lt;p&gt;That last one feels like the real opportunity to me. If anyone who has a positive experience with serverless can communicate its essential elements in a way that encourages others to try it — that’s how you build momentum. That’s the story worth telling.&lt;/p&gt;
&lt;p&gt;Next time you’re talking about serverless, or in fact, any decision. Think about the human-centered side of things. Think less about the technology, and more about how is this going to positively (or negatively) impact another human being. That will inevitable lead you to building better software.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>The Internet Gave Us Our Tribe and Took Away Our Neighbours</title><link>https://blog.jameseastham.co.uk/blog/2026-03-29-on-the-internet/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026-03-29-on-the-internet/</guid><description>The internet is brilliant at connecting like-minded people, but that same power might be quietly killing your diversity of ideas.</description><pubDate>Sun, 29 Mar 2026 10:58:36 GMT</pubDate><content:encoded>&lt;p&gt;The internet promised to connect us. Instead, it’s tearing us apart!&lt;/p&gt;
&lt;p&gt;The internet is one of the greatest achievements of humankind. A massively distributed and decentralized system with no single ‘owner’. The internet connected people across the world, gave a platform to voices your would never hear otherwise, and made information available to anyone with a phone signal.&lt;/p&gt;
&lt;p&gt;I recently read Deep Economy by Bill McKibben. A common theme in the book is to push for engagement with your local community and the people around you. &lt;a href=&quot;https://journals.sagepub.com/doi/10.1177/19485506251364333&quot;&gt;Studies&lt;/a&gt; have shown that almost every daily activity is better when engaging in it alongside other people, and what better to engage with than the ones close to you.&lt;/p&gt;
&lt;p&gt;You could argue that the internet has made this social interaction easier. With the push of a button I can connect with anyone, basically anywhere in the world. This is a wonderful thing. But it’s also a driver of the increase in division and the eroding of our shared humanity.&lt;/p&gt;
&lt;h2 id=&quot;social-connection-its-a-good-thing-right&quot;&gt;Social Connection, it’s a good thing right?&lt;/h2&gt;
&lt;p&gt;Before the internet, if you wanted to socialise, to exchange ideas, to just be around other people, you went to your local pub. Or a market. Or a community hall. And whoever showed up, showed up. Your neighbour with completely different political views. The guy from the other side of town with a totally different background. The older woman who’d lived through things you couldn’t imagine.&lt;/p&gt;
&lt;p&gt;The people you grew up around, the circles you were in. They were just there. You had very little control over that. This was a double edged sword. On one hand, you were &lt;em&gt;forced&lt;/em&gt; to spend time around people you might not necessarily agree with or even like. Diverse ideas spark better ideas and solutions. On the other hand, your gender/class/race/sexuality might have meant you meant certain circles or ways of thinking were inaccessible to you. This was, and still is, something we all collectively need to push against.&lt;/p&gt;
&lt;p&gt;Just think about how you spend your time online now though. I know how I spend mine. I follow people who think roughly like I do. I read news/content that broadly aligns with my interests and worldview. The algorithms quietly learn what keeps me engaged, and also what makes me angry, and serve me more of the same. And slowly, without really noticing, I end up in a little bubble of people who are a lot like me.&lt;/p&gt;
&lt;p&gt;Modern media (I’m grouping social and traditional together there) has moved to place that prioiritzes eyeballs/views/clicks over facts.&lt;/p&gt;
&lt;h2 id=&quot;the-false-promise-of-connection&quot;&gt;The False Promise of Connection&lt;/h2&gt;
&lt;p&gt;I’m not suggesting times before the internet were perfect. In Deep Economy Bill McKibben discusses talk radio. The whole premise of talk radio stations, and by extension all modern media, is that you can go an entire day without hearing a single opinion that you disagree with.&lt;/p&gt;
&lt;p&gt;Whilst talk radio stations might have this problem, at least there is an element of human editorial oversight. If you pick any given newspaper/radio station/podcast you can quickly asscertain what the subject matter is going to be. What the hosts views are. Whether it aligns to you. Whether it seems factual, sensationalist, or anything in between.&lt;/p&gt;
&lt;p&gt;Social media changes this dynamic completely. Now, there is a black box algorithm owned by a billionaire somewhere determining what is ‘valuable’ to you. You don’t know why you’re seeing this content. You just find yourself infinitely scrolling through a feed of content that someone else has decided that you will. Or, in a lot of cases, something that will make you angry.&lt;/p&gt;
&lt;p&gt;Only hearing ideas from people who think like you is self-affirming. Equally only hearing ideas that make you anrgy entrenches you in your beliefs.&lt;/p&gt;
&lt;p&gt;When you focus exclusively on these two things. Re-affirming or entrehcing your beliefts, you lose something amazing. The accidental collision of different perspectives. It’s a joyous moment when you hear someone say something you’d never have thought of, from a life you’ve never lived, and it genuinely changes how you see things.&lt;/p&gt;
&lt;p&gt;The way you view the world will be defined by your experiences. And your experiences are different to mine. If you encounter someone you disagree with, take a beat to ask yourself if you’d lived that persons exact experiences maybe would you find yourself thinking like them as well?&lt;/p&gt;
&lt;p&gt;A difference of opinion shouldn’t be about convincing the other person how right you are, it should be about being interested in each others ideas enough to both come out of the experience ‘better’.&lt;/p&gt;
&lt;p&gt;That used to happen almost by default, simply by being around enough people in face to face settings. Now, I’m not so sure. If you disagree with someone on the internet how do you deal with it? Quietely get angry, feel it rise up inside you? Maybe you angrily post on social media indirectly calling them out. Maybe you engage directly, reply to the person in question explaining how stupid they are and why they are wrong. I’ve been guilt of all of those things in the past.&lt;/p&gt;
&lt;p&gt;Face to face is a different situation. Remove the keyboard, put people face to face and humanity has a &lt;em&gt;chance&lt;/em&gt; of shining through. Eye contact triggers oxytocin, the ‘trust hormone.’ A handshake or a shared laugh disarms defensiveness. Online, we lack these cues—so we default to outrage. It doesn’t always. I’ve seen many a shouting match (and sometimes a physical match) from a differing in opinion. But keyboard warriors are real, and I’m sure you’ve all seen things on the internet and thought I don’t think they’d say that if they were in person.&lt;/p&gt;
&lt;h2 id=&quot;aim-for-1-better&quot;&gt;Aim For 1% better&lt;/h2&gt;
&lt;p&gt;How many of you actively seek out differing opinions to your own? This doesn’t have to be focused on the bigger challenges of humanity. It could be related to your day job, your relationship. Even what might seem like a micro decision, there is still value in understanding another persons perspective.&lt;/p&gt;
&lt;p&gt;Why would you do that? It’s uncomfortable. It’s easier to stay in the feed that feels familiar.&lt;/p&gt;
&lt;p&gt;Social media companies, and the media writ large employ hordes of people to grab your attention. Media is built to maximise engagement, and engagement goes up when you show people things that re-affirms their beliefs. Whether that’s through something they agree with, or something that makes them so angry it further entrenches what they believe.&lt;/p&gt;
&lt;p&gt;Does this accidental diversity of ideas still happens anywhere? Even if it does, does it happen in a constructive way. Maybe at work, if you’re lucky enough to be around people with genuinely different backgrounds and opinions. Maybe in person, depending on who’s in your social circles. Maybe in the comments section of the internet, although more often than not that descends into a shouting match rather than a genuine conversation.&lt;/p&gt;
&lt;p&gt;The internet gave us the ability to find our people, which is wonderful. But what did we give up in return. I challenge you all to ask yourself one simple question, how are you going to find some content that you disagree with and engage with it in a way where you seek to understand? Not where you seek to dismiss.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>On Flow, Focus &amp; Recovery</title><link>https://blog.jameseastham.co.uk/blog/on-recovery-flow-and-focus/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/on-recovery-flow-and-focus/</guid><description>I&apos;ve been thinking a lot lately about the relationship between doing deep, focused work and recovering from it properly. On the surface they seem like opposites. Work hard, then rest. Simple enough. But the more I dig into it, the more I think they&apos;re actually part of the same loop, and getting either one wrong breaks the whole thing.</description><pubDate>Sun, 15 Mar 2026 14:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve been thinking a lot lately about the relationship between doing deep, focused work and recovering from it properly. On the surface they seem like opposites. Work hard, then rest. Simple enough. But the more I dig into it, the more I think they’re actually part of the same loop, and getting either one wrong breaks the whole thing.&lt;/p&gt;
&lt;p&gt;This has become more important in the age of AI driven development. AI fatigure is real, &lt;a href=&quot;https://siddhantkhare.com/writing/ai-fatigue-is-real&quot;&gt;Siddhant Khare&lt;/a&gt; covered it on his blog. We are more productive than ever, shipping faster than ever, yet getting more exhausted. I’m certainly feeling it, I’m sure many of you reading are as well.&lt;/p&gt;
&lt;h2 id=&quot;the-flow-cycle&quot;&gt;The Flow Cycle&lt;/h2&gt;
&lt;p&gt;Flow is something I’ve been interested in for a long time. Not just the state itself, that feeling of being completely locked in where hours pass and you barely notice, but the actual cycle that surrounds it.&lt;/p&gt;
&lt;p&gt;What I’ve come to realise is that flow doesn’t just happen. You can’t sit down, open your laptop and will yourself into it. There’s a process. First, you have to struggle. You need to be working on something that sits right at the edge of your ability. Just frustrating enough that your brain is fully engaged, but not so far beyond you that you shut down completely. That tension is the entry point.&lt;/p&gt;
&lt;p&gt;Then comes the release. You step away. Go for a walk, make a coffee, do something completely unrelated. This is where I think a lot of people (myself included) get it wrong. The release feels like giving up, like you’re losing momentum. But that discomfort of stepping away is actually part of the process. Your brain needs that space to work through the problem without you consciously forcing it.&lt;/p&gt;
&lt;p&gt;After the release, you deploy whatever triggers help you drop back into focus. Then you’re back in it. And then the part that genuinely surprised me when I started paying attention to it: recovery. Proper, intentional recovery.&lt;/p&gt;
&lt;p&gt;This cycle is well studied, &lt;a href=&quot;https://www.stevenkotler.com&quot;&gt;Steven Kotler&lt;/a&gt; has wrote some fantastic books on the topic. In our current AI driven workflows, you could argue the struggle never happens and you never stop because the “just one more prompt” effect is real.&lt;/p&gt;
&lt;h2 id=&quot;recovery-isnt-passive&quot;&gt;Recovery Isn’t Passive&lt;/h2&gt;
&lt;p&gt;Here’s the thing I keep coming back to. Recovery sounds easy. It sounds like doing nothing. But in practice, it’s probably the hardest part of the whole cycle to actually commit to.&lt;/p&gt;
&lt;p&gt;When you could just write one more prompt, vibe one more feature, it’s very tricky.&lt;/p&gt;
&lt;p&gt;I have a restorative yoga practice I try to do as part of my daily shutdown. It’s maybe 20 minutes. Nothing dramatic. But the number of times I’ve let it slip because I worked late, or because I told myself I’d just finish this one thing first, is embarrassing. And those are exactly the days I need it most.&lt;/p&gt;
&lt;p&gt;It’s counterintuitive, but recovery actually requires grit. It requires the same commitment as the work itself. When things get hard, when the day runs over, when you’re tired and just want to sit on the sofa, the recovery protocols are the first things to go. But they’re the things that make the next day’s deep work possible.&lt;/p&gt;
&lt;p&gt;If you skip recovery consistently, you’re not just tired. You’re slowly degrading your ability to get into flow at all. The cycle breaks.&lt;/p&gt;
&lt;h2 id=&quot;deep-work-is-the-point&quot;&gt;Deep Work Is the Point&lt;/h2&gt;
&lt;p&gt;Underneath all of this is a question I keep asking myself. What am I actually trying to focus on?&lt;/p&gt;
&lt;p&gt;For me it comes down to a few things. Refining my craft, which means writing code, writing articles, producing content. Constant learning, reading a lot, actively trying to challenge my own views rather than just reinforcing them. Sharing intentionally. And being genuinely present during the things that matter.&lt;/p&gt;
&lt;p&gt;None of those are things I can do whilst half-distracted. You can’t refine a craft while checking Slack every ten minutes. You can’t really learn something deeply if you’re skimming it between meetings. You can’t be a productive meeting participant if you’re vibing with Claude on the side. These things demand focus, and focus is a finite resource that needs protecting.&lt;/p&gt;
&lt;p&gt;I’ll be the first to admit I’m guilt of all these things.&lt;/p&gt;
&lt;p&gt;My normal working day is full of interruptions. That’s just the reality of working in a team, in a company, with other humans who need things from me. So the deep work, the stuff that actually moves the needle on my own growth, has to happen outside of that. Early mornings, evenings, weekends. Time I carve out specifically because it’s mine to control.&lt;/p&gt;
&lt;p&gt;The question I try to keep asking is: is this the most important thing I could be doing right now? It’s a simple filter but it’s ruthless when you actually apply it honestly.&lt;/p&gt;
&lt;h2 id=&quot;the-loop&quot;&gt;The Loop&lt;/h2&gt;
&lt;p&gt;What I’ve ended up with is something like this. Deep, focused work requires flow. Flow requires struggle, release and the right triggers. And the whole thing is only sustainable with genuine recovery. Not passive, accidental recovery. Intentional, committed, even-when-you-don’t-want-to recovery.&lt;/p&gt;
&lt;p&gt;Grit isn’t just about pushing harder. Sometimes it’s about having the discipline to stop, to rest, to do the 20 minutes of yoga even though you’re tired and it’s late and you just want to be done with the day.&lt;/p&gt;
&lt;p&gt;The cycle only works if you respect every part of it.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Why .NET Devs Should Stop Writing Lambda YAML Forever</title><link>https://blog.jameseastham.co.uk/blog/2026-03-10-cdk-lambda-dotnet/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026-03-10-cdk-lambda-dotnet/</guid><description>Deploying .NET Lambda functions on AWS just got easier! In this video, you&apos;ll learn how to leverage the AWS Cloud Development Kit (CDK) to build, configure, and deploy serverless applications—no YAML, no tedious console clicking, and no need to master new syntaxes. Discover how CDK lets you use C# to define infrastructure, streamline permissions, and automate deployment, all within your familiar .NET workflow.</description><pubDate>Tue, 10 Mar 2026 16:01:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;infrastructure-shouldnt-be-this-hard&quot;&gt;Infrastructure Shouldn’t Be This Hard&lt;/h2&gt;
&lt;p&gt;Building out a serverless .NET application on AWS can feel like pushing a piano upstairs. Each step – creating Lambda functions, setting up API Gateway, defining DynamoDB tables, gluing it all together with IAM – can leave even experienced engineers tired. And don’t get me started on uploading zipped project files and hacking together permissions using YAML or console clicks. That isn’t just tedious, it’s a asking for errors and inconsistency.&lt;/p&gt;
&lt;p&gt;I’ve felt the sting of “isn’t there a better way?” far too often. There’s a reason we moved from hand-crafting EC2 instances to infrastructure-as-code: serverless should be even easier, right?&lt;/p&gt;
&lt;p&gt;Time for a reality check: it doesn’t have to be this painful. It’s 2026 after all, should we really be writing YAML anymore?&lt;/p&gt;
&lt;h2 id=&quot;a-better-way-cdk-for-net-developers&quot;&gt;A Better Way: CDK for .NET Developers&lt;/h2&gt;
&lt;p&gt;AWS’s CDK – Cloud Development Kit – is a quiet revolution for anyone serious about system architecture. Forget scribbling YAML or clicking through AWS’s console. With CDK, you define all your infrastructure and wiring in a familiar programming language. For .NET devs? Say hello to C#. Write actual code, leverage your IDE, and get the power of compile-time checks and IntelliSense. Deploying your infrastructure starts to feel like writing your app.&lt;/p&gt;
&lt;p&gt;Here’s how that looks in practice:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; Install&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; CDK&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; CLI&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; first&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; -g&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; aws-cdk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; Scaffold&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; CDK&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; project&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; C#:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;cdk&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; app&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; --language=csharp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You get a &lt;code&gt;Program.cs&lt;/code&gt; (entry point), and a stack class – essentially your blueprint for AWS resources. Everything lives in code, so you can refactor, reuse, and share custom constructs.&lt;/p&gt;
&lt;p&gt;Want an SQS queue? Spin up an SNS topic? Just instantiate the relevant class:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; queue&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Amazon&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CDK&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;AWS&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;SQS&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Queue&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;MyQueue&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;QueueProps&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; topic&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Amazon&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CDK&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;AWS&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;SNS&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Topic&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;MyTopic&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TopicProps&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Everything’s named intuitively. Your editor’s autocomplete all but eliminates time spent hunting documentation.&lt;/p&gt;
&lt;h2 id=&quot;compiling-net-lambda-no-more-zip-files&quot;&gt;Compiling .NET Lambda: No More Zip Files&lt;/h2&gt;
&lt;p&gt;Let’s tackle .NET Lambdas. Traditionally, you’re stuck compiling your app, zipping the output, uploading it manually (or with some awkward CLI script), and then crossing your fingers for a successful deployment. CDK brings sanity back: add &lt;code&gt;Amazon.CDK.AWS.Lambda.NET&lt;/code&gt;, and you can point the resource at your project directory. That’s it.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; myFunction&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DotnetFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;ItemsApiFunction&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DotnetFunctionProps&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    ProjectDir&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;../src/ItemsApi&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    // Specify handler, runtime, memory as needed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When CDK deploys, it handles compilation, packaging, and uploads automatically. No more manual zip files, no brittle scripts, and no wasted time.&lt;/p&gt;
&lt;p&gt;Even better: the Lambda Annotations framework (for .NET) generates helpful &lt;code&gt;serverless.template&lt;/code&gt; files so you can easily grab handler strings. It’s not just about ease–it’s about eliminating those subtle, recurring errors that make serverless adoption a headache.&lt;/p&gt;
&lt;h2 id=&quot;permissions-grant-dont-guess&quot;&gt;Permissions: Grant, Don’t Guess&lt;/h2&gt;
&lt;p&gt;IAM is a perennial pain point. Previously, you’d hack together policies, pray you had the right actions, and hope it all worked. CDK lets you grant specific permissions directly in code:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;table&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GrantReadWrite&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;myFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// DynamoDB table permission&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;myFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GrantInvoke&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;apiGateway&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Lambda invocation permission&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;queue&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GrantSendMessages&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;myFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// SQS publish permission&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This declarative approach is not just concise—it’s robust. The abstraction more closely matches how architects &lt;em&gt;think&lt;/em&gt; about relationships between components. No more YAML incantations or black-box IAM troubleshooting.&lt;/p&gt;
&lt;h2 id=&quot;wiring-up-the-api&quot;&gt;Wiring Up the API&lt;/h2&gt;
&lt;p&gt;API Gateway integrations are a notorious rabbit hole: create endpoints, wire up integrations, assign permissions, and then (finally) add routes. With CDK, you stay inside the world of C#, and, crucially, you can refactor and abstract repeated patterns.&lt;/p&gt;
&lt;p&gt;For example, to define an HTTP API with Lambda integrations:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; api&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;HttpApi&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;ItemsApi&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;HttpApiProps&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; integration&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaProxyIntegration&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Handler&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; myFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;api&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddRoutes&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;AddRoutesProps&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Path&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;/items&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Method&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; HttpMethod&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;POST&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Integration&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; integration&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You define API stages, integrations, and set permissions, all as code. It’s all composable, testable, and accessible to your whole team.&lt;/p&gt;
&lt;h2 id=&quot;custom-constructs-codify-best-practices&quot;&gt;Custom Constructs: Codify Best Practices&lt;/h2&gt;
&lt;p&gt;This is where things get interesting. Infrastructure code is finally just code–so you can leverage inheritance, composition, and abstraction. Imagine custom constructs that centralize repeated patterns: dead-letter queue wiring, API-Lambda integration scaffolding, security hardening. You can create custom classes and libraries, push them to your internal registry, and empower your team to reuse solid foundations.&lt;/p&gt;
&lt;p&gt;Say you had to make ten APIs with similar configuration. Previously, you’d copy-paste YAML, risk error, and throw consistency out the window. With CDK:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; ApiDotnetFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DotnetFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; ApiDotnetFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ApiProps&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; props&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) : &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;base&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;props&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    // Wiring up integration, routes, permissions centralised here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, deploy a new Lambda with API integration by instantiating a single construct. It’s as DRY (and as powerful) as any application code. Need loops and conditionals? Use them. Need custom logic for config? Go wild. Best practice becomes encapsulated, not bolted-on.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Lambda Function - CDK builds and packages automatically&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; getAllItemsFunction&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ApiDotnetFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;ItemsFunction&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ApiDotnetFunctionProps&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    ProjectDir&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;../src/ItemsApi&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Handler&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;ItemsApi::ItemsApi.Functions_GetAllItems_Generated::GetAllItems&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Runtime&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Runtime&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DOTNET_10&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    MemorySize&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 512&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Timeout&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Duration&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Seconds&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt;30&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Environment&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Dictionary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        { &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;TABLE_NAME&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;table&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TableName&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Api&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; api&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    RouteKey&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;GET /items&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Region&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Region&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Account&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Account&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;nothing-else-to-learn&quot;&gt;Nothing Else to Learn&lt;/h2&gt;
&lt;p&gt;The heart of modern serverless engineering is about minimizing friction. CDK for .NET lets you write both your application and infrastructure code in C#. No switch to YAML, Terraform syntax, or ever more brittle scripting. You can leverage your existing skill set, move fast, and make fewer mistakes–all while unlocking the expressive power of typed languages.&lt;/p&gt;
&lt;h2 id=&quot;practical-takeaway&quot;&gt;Practical Takeaway&lt;/h2&gt;
&lt;p&gt;Serverless was supposed to abstract away the pain. Yet until recently, for .NET devs, deploying meaningful apps felt half-baked. The AWS CDK transforms that landscape. By merging infrastructure and application logic into code, you get the harmony you always wanted: deep reuse, expressive abstractions, and a consistent deployment model.&lt;/p&gt;
&lt;p&gt;Try out CDK in your next project. Refactor construct patterns. Push your infra classes to your internal registry. Treat infra code as engineering, not bureaucracy. Move your teams up the stairs and keep the music playing.&lt;/p&gt;
&lt;p&gt;Curious for hands-on visuals? Check out the &lt;a href=&quot;https://youtu.be/sX3K1tIwYnw&quot;&gt;video version of this blog post&lt;/a&gt;.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>You&apos;re Crazy To Think You Can Predict Your Next Outage!</title><link>https://blog.jameseastham.co.uk/blog/you-cant-predict-your-outage/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/you-cant-predict-your-outage/</guid><description>Here&apos;s something that took me a while to really accept: we&apos;re genuinely terrible at predicting problems in our systems before they happen. Not because we&apos;re bad engineers. It&apos;s just how humans work.</description><pubDate>Sun, 01 Mar 2026 16:02:00 GMT</pubDate><content:encoded>&lt;p&gt;You’re probably terrible at predicting the next outage in your system!&lt;/p&gt;
&lt;p&gt;Not because you’re a bad engineer, I’m guilty of it too. It’s just how we humans work. You’ll have a mental model of what &lt;em&gt;could&lt;/em&gt; go wrong based on what &lt;em&gt;has&lt;/em&gt; gone wrong. If a particular type of failure has never hit your system, the odds of you proactively designing against it are pretty slim. You don’t know what you don’t know.&lt;/p&gt;
&lt;p&gt;This has some pretty uncomfortable implications for how you might think about reliability. And even more implications as you move further away from writing individual lines of code yourself, into the world of LLM’s software for you.&lt;/p&gt;
&lt;h2 id=&quot;the-monitoring-trap&quot;&gt;The Monitoring Trap&lt;/h2&gt;
&lt;p&gt;The classic response to “how do we know when things go wrong?” is to add more monitoring. Dashboards, alerts, thresholds. CPU over 80%? Alert. Error rate above 1%? Alert. P99 latency over 500ms? Alert.&lt;/p&gt;
&lt;p&gt;Imagine you have an outage, your pager goes off at 2am because something’s wrong. You sleepily stumble out of bed, and open up your observability platform of choice. You see that the production RDS instance has ran out of disk space. Annoying, but a relatively easy fix. You bundle more memory into the instance (gotta love the cloud) and then go back to bed.&lt;/p&gt;
&lt;p&gt;Hopefully, the next day you run some kind of post-mortem. And one of the probable outcomes of that to create some kind of monitor watching the disk space. If the disk space is over 80%, notify somebody. Problem solved.&lt;/p&gt;
&lt;p&gt;This kind of stuff has value. But it’s &lt;em&gt;not&lt;/em&gt; observability. There’s a really important distinction between monitoring and observability, and conflating the two is where you’re going to get stuck.&lt;/p&gt;
&lt;p&gt;Monitoring tells you when something you already anticipated is happening. You set a threshold because you know that metric matters. You’ve seen it spike before. You know what it means.&lt;/p&gt;
&lt;p&gt;Observability is different. Observability is the ability to sit down at any point in time, ask &lt;em&gt;any&lt;/em&gt; question about your system, and actually get an answer. Slice the data in ways you hadn’t thought of before. Follow breadcrumbs back through a chain of events to find the actual root cause, not just the symptom.&lt;/p&gt;
&lt;p&gt;Logs, metrics and traces (and to some extent profiling) aren’t observability. They’re the raw material. What you do with them, and how flexibly you can query and explore them, that’s where observability actually lives.&lt;/p&gt;
&lt;p&gt;The reason this matters so much comes back to that first point. If you can only answer questions you thought to ask in advance, you’re stuck inside your own mental model of how the system can fail. And your mental model has gaps. It always does.&lt;/p&gt;
&lt;h2 id=&quot;metrics-for-systems-observability-for-software&quot;&gt;Metrics for Systems, Observability for Software&lt;/h2&gt;
&lt;p&gt;One thing that’s helped me think about this more clearly is drawing a line between the components my application runs on top of, and the application itself.&lt;/p&gt;
&lt;p&gt;Infrastructure has a fixed-ish set of constraints and problems. Redis starts to fall over under certain memory pressure. Kafka consumer lag grows when throughput spikes. EC2 instances hit CPU/memory limits. These failure modes are well understood, well documented, and relatively stable. Metrics work brilliantly here. Set your thresholds, configure your auto-scaling, and you’re largely covered.&lt;/p&gt;
&lt;p&gt;If you’re running something like Nginx and want to check the traffic running through it, logs are about your only option. Stream the logs from Nginx and do something with them. The same goes for Amazon CloudTrail logs. Many infrastructure services output logs in some shape or form, and that’s really helpful.&lt;/p&gt;
&lt;p&gt;The software your (or Claude) writes is a completely different story. Application code changes constantly. A new feature ships, a refactor lands, a dependency gets bumped. Any metric threshold you defined last month might be completely meaningless today because the code it was measuring looks nothing like it did when you set it.&lt;/p&gt;
&lt;p&gt;These changes are also being made by several people. Whether you’re running a lean, vibe-coded startup or part of an enormous development organisation. There are multiple parties contributing to the code base. And all those parties will probably have a slightly different mental model of the system, and a very different set of previous experiences. I use the word parties intentionally, I’d include coding assistants in that bucket as well.&lt;/p&gt;
&lt;p&gt;On top of all of that, an individual software component runs as part of a larger system. The complexity of a system emerges from the interactions between the parts, not the individual parts themselves. And when you truly consider the &lt;em&gt;entire&lt;/em&gt; system, the software components, the developers, coding assistants, the product managers, executive leadership, executive leaders using LLM’s to make decisions, users of he software, prospects of the software, the cloud provider you use to host everything and everything else.&lt;/p&gt;
&lt;p&gt;All of which is changing constantly. Not so simple is it.&lt;/p&gt;
&lt;p&gt;This is where the ability to ask arbitrary questions of your system becomes genuinely useful. Instead of asking “is this metric above the threshold I set six weeks ago?”, you can ask “how does this system behave &lt;em&gt;right now&lt;/em&gt; compared to before this deployment?”. That kind of comparison, made freely and without having to pre-define everything, is what lets you keep up with software that never stops changing.&lt;/p&gt;
&lt;h2 id=&quot;designing-for-change-in-the-first-place&quot;&gt;Designing for Change in the First Place&lt;/h2&gt;
&lt;p&gt;Which brings me to something I think gets undervalued in many architectural conversations: the rate of change itself is something worth designing for. I’d argue evolvability is the most important ‘-ility’.&lt;/p&gt;
&lt;p&gt;Speed of change is a competitive advantage. If you can ship safely, iterate quickly, and roll back confidently you have an advantage over other teams that are scared of their own codebase. Some of what might scare you about your codebase is accidental complexity that’s crept in over time.&lt;/p&gt;
&lt;p&gt;Or the fact the whole thing has been vibe-coded with little to no thoughts about software quality.&lt;/p&gt;
&lt;p&gt;One area where I see this play out is in how teams think about reuse. There’s a real temptation to build reusable components early. It feels responsible. It feels like good engineering. But I’ve been burned by this enough times to be pretty cautious about it now.&lt;/p&gt;
&lt;p&gt;Build the thing first. Use it in one place. Understand it properly. &lt;em&gt;Then&lt;/em&gt; think about reuse. Premature abstraction is its own kind of complexity, and unpicking a badly designed abstraction that’s been reused in fifteen places is a painful way to spend a sprint.&lt;/p&gt;
&lt;p&gt;The exception I’d make here is around observability and schema design. Getting those right early, and building them consistently, tends to pay for itself pretty quickly.&lt;/p&gt;
&lt;h2 id=&quot;making-illegal-states-impossible&quot;&gt;Making Illegal States Impossible&lt;/h2&gt;
&lt;p&gt;One of my favourite ways to reduce the surface area for unexpected failures is to make invalid states literally impossible to represent in code.&lt;/p&gt;
&lt;p&gt;Take something like an email address. In a lot of systems, an email can be verified or unverified, and that distinction gets tracked with a boolean flag somewhere. Which means somewhere in the codebase, some function that &lt;em&gt;should&lt;/em&gt; only operate on verified emails is probably trusting that the caller checked the flag. Or maybe it isn’t. Hard to tell.&lt;/p&gt;
&lt;p&gt;A better approach is to make these two things separate types. &lt;code&gt;UnverifiedEmail&lt;/code&gt; and &lt;code&gt;VerifiedEmail&lt;/code&gt;. The constructor for &lt;code&gt;VerifiedEmail&lt;/code&gt; is private, and the only way to get one is through a verification service that you actually trust. Now any function that needs a verified email just takes a &lt;code&gt;VerifiedEmail&lt;/code&gt; as a parameter. The compiler enforces the rule. You can’t pass an unverified email in by accident because the types won’t let you.&lt;/p&gt;
&lt;p&gt;This is the kind of thing that sounds like a small detail but compounds nicely across a whole codebase. Fewer implicit assumptions. Fewer “I assumed the caller had already checked that” bugs. Fewer surprises at 2am.&lt;/p&gt;
&lt;p&gt;These are also the kinds of things that LLM written code will &lt;strong&gt;never&lt;/strong&gt; do without explicit prompting, they just don’t think that way.&lt;/p&gt;
&lt;h2 id=&quot;you-cant-predict-everything-so-stop-trying&quot;&gt;You Can’t Predict Everything, So Stop Trying&lt;/h2&gt;
&lt;p&gt;Coming back to where I started. You can’t predict every failure. You can’t anticipate every question you’ll want to ask about your system when something goes wrong at 2am. And you can’t design away every edge case before it surfaces in production.&lt;/p&gt;
&lt;p&gt;There’s no way you could even see all the different edges, let alone track them.&lt;/p&gt;
&lt;p&gt;What you &lt;em&gt;can&lt;/em&gt; do is build systems that are easier to understand when things go wrong. Invest in real observability so you can ask questions you haven’t thought of yet. Design your application code so that change is cheap and safe. Push complexity down to the infrastructure layer where failure modes are predictable, and keep your application layer as clean and queryable as possible.&lt;/p&gt;
&lt;p&gt;The goal isn’t a system that never breaks. It’s a system where, when it does break, you can actually figure out why.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Conquer .NET Lambda Performance with these 3 steps</title><link>https://blog.jameseastham.co.uk/blog/2026-02-23-performant-dotnet-lambda/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2026-02-23-performant-dotnet-lambda/</guid><description>Running .NET on AWS Lambda? Follow these steps to ensure you&apos;re getting the best possible performance for your workload</description><pubDate>Tue, 24 Feb 2026 16:01:00 GMT</pubDate><content:encoded>&lt;p&gt;Every engineer working in serverless has felt the sting of a cold start at least once. There you are, full of anticipation, hitting an API endpoint only to stare at your screen, twiddling your thumbs, wondering if AWS Lambda has gone on holiday or something. When the response finally arrives, it’s often paired with frustration, confusion, and a twinge of embarrassment if there was a team member watching over your shoulder. For us .NET, and Java, developers this problem can be particularly pronounced.&lt;/p&gt;
&lt;p&gt;I know of entire organizations who have completely re-written their whole stack because of this challenge.&lt;/p&gt;
&lt;p&gt;Cold starts aren’t just a curiosity—they’re an architectural bottleneck, a design constraint, and a UX reality all at once. But like most “impossible” problems in distributed systems, once you peel away the mystery, a set of actionable strategies emerges. Let’s dig into why .NET Lambda cold starts loom so large, and what you can do—today—to whittle those waits away.&lt;/p&gt;
&lt;h2 id=&quot;memory-allocation-the-undervalued-lever&quot;&gt;Memory Allocation: The Undervalued Lever&lt;/h2&gt;
&lt;p&gt;There’s a certain badge of honor in minimizing your Lambda function’s memory allocation. It feels frugal, architectural, green. But here’s the kicker: your memory setting isn’t just about RAM. AWS Lambda ties your CPU allocation directly to how much memory you request. Pick the smallest memory footprint, and you’ll get a low powered CPU as well.&lt;/p&gt;
&lt;p&gt;That 128 MB Lambda function? It might be cheap, but it’s also starved for compute. That translates, under the covers, to lethargic cold starts—exactly the pain you see when the clock ticks and nothing seems to happen.&lt;/p&gt;
&lt;p&gt;Start with a gigabyte. I know, I know, it feels excessive, but you’ve got to think in Lambda’s logic. Jumping from 128 MB to 1 GB can transform a 9.2 second build duration into a 1.2 second response for .NET Lambda. Even at a glance, it’s clear that frugality can cost you more—both in user patience and, depending on your workload, in real money.&lt;/p&gt;
&lt;p&gt;Still skeptical or want to optimize further? Try the open-source &lt;a href=&quot;https://github.com/alexcasalboni/aws-lambda-power-tuning&quot;&gt;AWS Lambda Power Tuning&lt;/a&gt; tool. Let it hammer your function with various memory allocations. More often than not, you’ll see a sweet spot emerge where performance improves and costs diminish beyond what intuition suggests.&lt;/p&gt;
&lt;h2 id=&quot;initialization-the-secret-to-fast-successive-invocations&quot;&gt;Initialization: The Secret to Fast Successive Invocations&lt;/h2&gt;
&lt;p&gt;The first invoke pays for all your mistakes. SDK initialization, secrets fetching, client construction—pack those all into your handler and you’ll relive cold start pain every single time. Systems thinking means designing for the lifecycle Lambda gives you: exploitation of &lt;a href=&quot;https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html&quot;&gt;“execution environments”&lt;/a&gt; that stick around for future requests.&lt;/p&gt;
&lt;p&gt;In plain speak: anything that can be set up once and reused across invocations should be. In .NET, that means initializing heavy objects (like AWS SDK clients or configuration data) in the constructor or a startup class, rather than every single time the handler is called. .NET’s Lambda Annotations Framework is brilliant for this pattern. As well as simplifying your handlers code, it also brings in familiar dependency injection principles.&lt;/p&gt;
&lt;p&gt;The mechanics are simple. Suppose you’re using the modern Lambda Annotations-based model:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; MyLambdaFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IAmazonDynamoDB&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; ddbClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;HttpClient&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; httpClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;AppConfig&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; config&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;APIGatewayProxyRequest&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        // Handler code here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’d have a &lt;code&gt;Startup.cs&lt;/code&gt; file that looked a little bit something like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaStartup&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Startup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; ConfigureServices&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IServiceCollection&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; services&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;        services&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddSingleton&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IAmazonDynamoDB&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;AmazonDynamoDBClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;        services&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddHttpClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; apiKey&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; FetchSecretSync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;        services&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddSingleton&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;AppConfig&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;            ApiKey&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; apiKey&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;            TableName&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Environment&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GetEnvironmentVariable&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;TABLE_NAME&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) ?? &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Products&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; FetchSecretSync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        try&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            using&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; secretsClient&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;AmazonSecretsManagerClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; secretResponse&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; secretsClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GetSecretValueAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;GetSecretValueRequest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;                SecretId&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Environment&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GetEnvironmentVariable&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;SECRET_NAME&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) ?? &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;my-api-key&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }).&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GetAwaiter&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GetResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; secretResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;SecretString&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; ?? &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;default-key&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        catch&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;Could not fetch secret: &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Message&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;. Using default.&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;default-key&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Objects get initialized once per execution environment, rather than on every invocation. That means after the cold start, followup requests can be lightning fast—single-digit millisecond response times aren’t uncommon.&lt;/p&gt;
&lt;p&gt;What’s so powerful here is that Lambda’s initialization phase (the &lt;code&gt;init duration&lt;/code&gt;) gets a CPU boost behind the scenes: if your memory setting entitles you to, say, 1.5 vCPUs, Lambda rounds up and gives you 2 during init. That’s a “free” burst you can harness for heavy startup tasks.&lt;/p&gt;
&lt;p&gt;The knock on effect, is that you also write more testable handlers as well.&lt;/p&gt;
&lt;h2 id=&quot;native-aot-henry-ford-for-your-lambdas&quot;&gt;Native AOT: Henry Ford for Your Lambdas&lt;/h2&gt;
&lt;p&gt;For greenfield APIs and microservices, there’s a not so new anymore tool in the .NET arsenal: &lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8&quot;&gt;Native Ahead-Of-Time (AOT) compilation.&lt;/a&gt; .NET typically relies on a JIT (Just-In-Time compiler), converting IL code into machine instructions when the Lambda spins up. Native AOT flips that on its head, compiling down to a native binary ahead of time. The cold start penalty from the JIT almost vanishes.&lt;/p&gt;
&lt;p&gt;Caveats loom. Reflection-based features don’t play well with AOT, so you’ll need to retool serialization and similar patterns. For example, JSON serialization/deserialization must use source generators. Here’s a rough sketch of what that looks like in code:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;JsonSerializable&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;APIResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;))]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;JsonSerializable&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;APIGatewayProxyRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;))]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;JsonSerializable&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;))]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; partial&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; LambdaJsonContext&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;JsonSerializerContext&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Switching to source-generated serialization means you must explicitly list the types you want handled—no wildcards. But the performance benefits speak for themselves, cold starts dropping to as little as 300 milliseconds, total. For a modern API, that rivals the fastest interpreted runtimes out there—go ahead, compare it to Node.js or Go. Alright alright Rust developers calm down though, you’re still the most performant Lambda runtime.&lt;/p&gt;
&lt;h2 id=&quot;it-all-adds-up-a-systems-view&quot;&gt;It All Adds Up: A Systems View&lt;/h2&gt;
&lt;p&gt;Serverless isn’t “magic.” It’s a set of trade-offs, many of them masked by abstraction. But as you can see, the cold start challenge is best tackled not by a single fix, but by layering solutions: appropriate resource allocation, smart initialization, and native compilation.&lt;/p&gt;
&lt;p&gt;It’s systems thinking in action—a holistic approach that sees cold start latency as the emergent property of resource allocation, object lifetimes, and compilation mode.&lt;/p&gt;
&lt;h2 id=&quot;want-to-see-this-in-action&quot;&gt;Want to See This in Action?&lt;/h2&gt;
&lt;p&gt;Seeing is believing. If you’re hungry for benchmarks, concrete configuration steps, and even more technical deep dives, check out the &lt;a href=&quot;https://youtu.be/roIIujtLaQ4&quot;&gt;video version of this post here&lt;/a&gt;.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Writing testable, maintable, Lambda Functions in .NET</title><link>https://blog.jameseastham.co.uk/blog/structure-your-lambda-functions/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/structure-your-lambda-functions/</guid><description>Moving fast is exhilarating, until it&apos;s 3am and you&apos;re knee-deep in a sea of 700-line Lambda functions, trying to swat a bug that only appears on production. The question that lingers for many .NET engineers venturing into serverless is: does adopting Lambda mean sacrificing testability, maintainability, and all the hard-won architecture patterns from the rest of your career?</description><pubDate>Wed, 11 Feb 2026 16:02:43 GMT</pubDate><content:encoded>&lt;h1 id=&quot;writing-testable-maintainable-lambda-functions-in-net-beyond-the-big-ball-of-mud&quot;&gt;Writing Testable, Maintainable Lambda Functions in .NET: Beyond the Big Ball of Mud&lt;/h1&gt;
&lt;p&gt;Moving fast is exhilarating, until it’s 3am and you’re knee-deep in a sea of 700-line Lambda functions, trying to swat a bug that only appears on production. The question that lingers for many .NET engineers venturing into serverless is: does adopting Lambda mean sacrificing testability, maintainability, and all the hard-won architecture patterns from the rest of your career?&lt;/p&gt;
&lt;p&gt;If you’ve ever squinted at a monolithic function full of parsing, validation, business rules, database operations, and notification logic—crammed together in a mess that’s impossible to unit test—welcome to the club. But here’s the good news: serverless doesn’t have to mean “abandon all engineering discipline.” In fact, your Lambda functions can be clean, decoupled, and a joy to work with, just like the best of your ASP.NET codebases.&lt;/p&gt;
&lt;p&gt;Let’s look at how applying separation of concerns and dependency injection to .NET Lambdas (with a little help from the Lambda Annotations framework) can transform not just your code, but your productivity, test coverage, and on-call sanity.&lt;/p&gt;
&lt;h2 id=&quot;surfacing-the-real-problem-untangling-the-ball-of-mud&quot;&gt;Surfacing the Real Problem: Untangling the Ball of Mud&lt;/h2&gt;
&lt;p&gt;I still remember opening what should have been a simple Lambda handler, only to scroll through hundreds of lines of code. Parsing requests. Manually deserializing bodies. Inline validation logic. Database queries and updates interleaved with business rules. “Quick” bug fixes took hours because every change risked unintended side effects, and writing effective unit tests was next to impossible.&lt;/p&gt;
&lt;p&gt;Sound familiar? Here’s a snipped-down example of what these functions often look like:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; FunctionHandler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;APIGatewayProxyRequest&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Deserialize order&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; order&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; JsonConvert&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;DeserializeObject&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OrderRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Body&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Validate order (customerId, items, email address, etc)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;IsNullOrEmpty&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CustomerId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; ... )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; BadRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Invalid order&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Run business logic&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Query DynamoDB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// More business logic&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Publish notification&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// ... hundreds more lines ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Making changes here is like pulling a thread on a wool sweater: you fix one thing, and the whole thing unravels.&lt;/p&gt;
&lt;h2 id=&quot;a-better-way-structuring-serverless-net-like-grown-up-software&quot;&gt;A Better Way: Structuring Serverless .NET Like Grown-Up Software&lt;/h2&gt;
&lt;p&gt;There’s nothing inherent to Lambda or serverless that requires abandoning SOLID principles. Part of the shift is recognizing that your Lambda handler is just an entrypoint—it shouldn’t &lt;em&gt;own&lt;/em&gt; all the work.&lt;/p&gt;
&lt;p&gt;The solution is to treat your Lambda like you would a controller in ASP.NET: keep it thin and delegate everything else.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Parsing and Routing&lt;/strong&gt;&lt;br&gt;
The &lt;a href=&quot;https://docs.aws.amazon.com/lambda/latest/dg/dotnet-annotations.html&quot;&gt;Amazon Lambda Annotations&lt;/a&gt; framework brings modern annotation-driven programming to .NET Lambdas. You can decorate your handler so it automatically receives parsed request bodies, dramatically reducing boilerplate.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;HttpApi&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaHttpMethod&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Post&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;/orders&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IHttpResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ProcessOrderAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;([&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;FromBody&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OrderRequest&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; orderRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;   // We&apos;ll fill this in soon...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just like in ASP.NET MVC, you annotate your parameters and let the framework handle parsing.&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Validation&lt;/strong&gt;&lt;br&gt;
Inline validation logic sprinkled throughout the function breeds chaos. Extract it behind an interface:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; interface&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; IOrderValidator&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;   ValidationResult&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Validate&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OrderRequest&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; order&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This not only cleans up your handler, but lets you swap in different validators or leverage existing libraries like FluentValidation.&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;Business Logic Isolation&lt;/strong&gt;&lt;br&gt;
Following the Ports and Adapters (a.k.a. Hexagonal Architecture) pattern, pull all your “core” business logic into well-defined services:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; interface&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; IOrderService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;   Task&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OrderResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ProcessAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OrderRequest&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; order&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your Lambda handler simply orchestrates: parse, validate, process, return a response.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IHttpResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ProcessOrderAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;([&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;FromBody&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OrderRequest&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;   var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; validation&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; _orderValidator&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Validate&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;   if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;validation&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IsValid&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; BadRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;validation&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Errors&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;   var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; result&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_orderService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ProcessAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;   if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Success&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; BadRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;FailReason&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;   return&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Created&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OrderId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Centralized Models &amp;amp; DI&lt;/strong&gt;&lt;br&gt;
Move your models (requests, responses, validation results) to a shared &lt;code&gt;Models&lt;/code&gt; folder, and use a &lt;code&gt;Startup.cs&lt;/code&gt; (or modern &lt;code&gt;.NET&lt;/code&gt; pattern with &lt;code&gt;Program.cs&lt;/code&gt;) to register dependencies with the Lambda dependency injection container.&lt;/p&gt;
&lt;p&gt;Now, your codebase mirrors everything that’s good about modern .NET server applications.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;testability-the-payoff&quot;&gt;Testability: The Payoff&lt;/h2&gt;
&lt;p&gt;Here’s where the magic happens: once you’ve factored your Lambda in this way, writing tests becomes almost trivial.&lt;/p&gt;
&lt;p&gt;Your handler is just a class with dependencies. You can inject fakes or mocks for &lt;code&gt;IOrderValidator&lt;/code&gt; and &lt;code&gt;IOrderService&lt;/code&gt; and unit test your function logic directly—no need to spin up Docker, mock cloud APIs, or wrangle YAML.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Fact&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; ReturnsBadRequest_WhenValidationFails&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; orderValidator&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Mock&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IOrderValidator&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;    orderValidator&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Setup&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Validate&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;It&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;IsAny&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OrderRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;()))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Returns&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ValidationResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;IsValid&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Errors&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Invalid!&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; } });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; orderService&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Mock&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IOrderService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(); &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; handler&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OrderFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;orderValidator&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;orderService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; response&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ProcessOrderAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OrderRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()); &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Assert&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;IsType&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;BadRequestResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;response&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Suddenly, all those patterns you painstakingly learned about isolation and dependency injection aren’t just possible—they’re &lt;em&gt;natural&lt;/em&gt; in serverless .NET.&lt;/p&gt;
&lt;h2 id=&quot;so-why-does-this-still-go-wrong&quot;&gt;So Why Does This Still Go Wrong?&lt;/h2&gt;
&lt;p&gt;The temptation is real: with .NET 10’s single-file Lambda features, it’s never been easier to slap a bunch of code into one file and deploy. It feels fast… right until you’re in maintenance purgatory. “Quick and dirty” compounds–the simple demo becomes tomorrow’s production headache.&lt;/p&gt;
&lt;p&gt;There is a cognitive pressure in serverless to just ship the function, but production-ready systems thrive on discipline. Clear separation of concerns is just as important in the cloud as anywhere else—arguably more, because you’re often dealing with multiple data sources, event triggers, and team members.&lt;/p&gt;
&lt;h2 id=&quot;the-principle-treat-your-lambda-functions-like-any-other-code&quot;&gt;The Principle: Treat Your Lambda Functions Like Any Other Code&lt;/h2&gt;
&lt;p&gt;When you build serverless systems, resist the urge to compromise on code quality. Use dependency injection, model binding, clear business/service layer boundaries, and write tests that don’t require the cloud to run. Your future self will thank you.&lt;/p&gt;
&lt;p&gt;A Lambda handler should feel like a short, readable story: &lt;em&gt;Validate. Process. Return.&lt;/em&gt; Everything else belongs somewhere more appropriate.&lt;/p&gt;
&lt;p&gt;Don’t settle for spaghetti. Compose your functions with the same care—and you’ll ship faster, debug easier, and sleep better.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Want a deeper dive, or prefer to see it in action? Check out the video walkthrough version of this post on &lt;a href=&quot;https://youtu.be/_EIndrP94Lw&quot;&gt;YouTube&lt;/a&gt; and see clean Lambda structure come to life!&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>.NET on AWS Lambda in 20 minutes</title><link>https://blog.jameseastham.co.uk/blog/dotnet-on-lambda-10-minutes/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/dotnet-on-lambda-10-minutes/</guid><description>Staring at a greenfield project, most engineers face that twinge of anxiety. You know the feeling: you want to move fast, lean on your experience, but there&apos;s this wall—deploying your .NET API to serverless without losing the developer ergonomics you love from ASP.NET. That&apos;s the heart of the issue. Serverless is supposed to save us operational headaches, but how do you keep your flow when the abstraction starts to diverge from your muscle memory?</description><pubDate>Wed, 28 Jan 2026 16:02:43 GMT</pubDate><content:encoded>&lt;h1 id=&quot;feels-like-aspnet-runs-on-lambda-under-10-minutes-to-serverless-apis-with-net-aspire&quot;&gt;Feels Like ASP.NET, Runs on Lambda: Under 10 Minutes to Serverless APIs with .NET Aspire&lt;/h1&gt;
&lt;h2 id=&quot;the-line-between-the-familiar-and-the-future-in-cloud-native-net&quot;&gt;The line between the familiar and the future in cloud-native .NET&lt;/h2&gt;
&lt;p&gt;Staring at a greenfield project, most engineers face that twinge of anxiety. You know the feeling: you want to move fast, lean on your experience, but there’s this wall—deploying your .NET API to serverless without losing the developer ergonomics you love from ASP.NET. That’s the heart of the issue. Serverless is supposed to save us operational headaches, but how do you keep your flow when the abstraction starts to diverge from your muscle memory?&lt;/p&gt;
&lt;p&gt;Recently, the rise of .NET Aspire and the Lambda Annotations framework has begun to close that psychological (and technical) gap. With the right approach, you can build .NET APIs for AWS Lambda with the confidence and patterns you’d expect from mature ASP.NET—without losing momentum or getting trapped in YAML purgatory. And, if you’re fast, all of this can be live in less than ten minutes.&lt;/p&gt;
&lt;h2 id=&quot;the-familiarity-principle-serverless-without-sacrificing-syntax&quot;&gt;The Familiarity Principle: Serverless Without Sacrificing Syntax&lt;/h2&gt;
&lt;p&gt;Software engineers love muscle memory. That’s why so many engineers bounce off early serverless: the friction of learning new SDKs, puzzling over cryptic handler strings, and wrestling with unfamiliar deployment models. What if you didn’t have to?&lt;/p&gt;
&lt;p&gt;That’s where Lambda Annotations come in. You set up your project as you would with an ordinary ASP.NET API—no need to break old habits. Here’s a taste:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Functions&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; ICalculatorService&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; _calculatorService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Functions&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ICalculatorService&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; calculatorService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;_calculatorService&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; calculatorService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;HttpApi&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(HttpMethod &lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;GET&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, Path &lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;/add/{x}/{y}&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Add&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; y&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_calculatorService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Add&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’re reading it right. Endpoints are just class methods, annotated with &lt;code&gt;[LambdaFunction]&lt;/code&gt; and &lt;code&gt;[HttpApi]&lt;/code&gt;, mapping HTTP paths and verbs just like classic ASP.NET. Path parameters? Handled through names—you don’t fumble with routing tables or hand-rolled API Gateway event parsing.&lt;/p&gt;
&lt;p&gt;Want to accept a typed payload? Add a POST endpoint, use a &lt;code&gt;[FromBody]&lt;/code&gt; parameter, and let the framework handle parsing:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;HttpApi&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(HttpMethod &lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;POST&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, Path &lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;/post&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Post&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;([&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;FromBody&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;MyData&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; data&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;You said: &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Hello&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result: refactoring, DI, and endpoint development feel exactly like an old-school ASP.NET project. And all that complexity AWS used to force on you—the ugly handler strings, the cloudformation glue—is boiled down to a thin, readable abstraction.&lt;/p&gt;
&lt;h2 id=&quot;configuration-done-right-dependency-injection-and-that-startupcs-nostalgia&quot;&gt;Configuration Done Right: Dependency Injection and That Startup.CS Nostalgia&lt;/h2&gt;
&lt;p&gt;For those who’ve grown up with .NET, the &lt;code&gt;Startup.cs&lt;/code&gt; file is almost sacred ground. It’s the heart of your app’s configuration, and it keeps your engineering fast and organized. Even as new patterns like minimal APIs have taken hold, there’s value in having a central place for dependency injection, configuration builders, and service registration.&lt;/p&gt;
&lt;p&gt;Lambda Annotations respects that. Your &lt;code&gt;Startup.cs&lt;/code&gt; lives on:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Startup&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; ConfigureServices&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IServiceCollection&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; services&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;    services&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddSingleton&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ICalculatorService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CalculatorService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; config&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ConfigurationBuilder&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddEnvironmentVariables&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Build&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;    services&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddSingleton&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IConfiguration&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not quite as magic as DI in classic ASP.NET Core—there’s a bit of hands-on work for configuration—but it’s recognizable. Adding AWS SDKs or custom secrets logic goes here, and &lt;code&gt;IConfiguration&lt;/code&gt; flows everywhere it needs to go.&lt;/p&gt;
&lt;p&gt;The upshot: moving your codebase from POC to production won’t mean undoing months of “serverless special-case” hacks. Changes stay predictable, understandable, and close to conventional engineering wisdom.&lt;/p&gt;
&lt;h2 id=&quot;the-reality-under-the-hood-source-generators-and-infrastructure-simplified&quot;&gt;The Reality Under the Hood: Source Generators and Infrastructure Simplified&lt;/h2&gt;
&lt;p&gt;Here’s the deal nobody talks about with serverless: the glue code is exhausting. Most Lambda guides ask you to hand-craft handler functions, stubbing out JSON parsing of APIGateway Proxy events until your eyes cross. But with .NET 10 and the Lambda Annotations framework, the ceremony is—finally—gone.&lt;/p&gt;
&lt;p&gt;What’s actually happening? As you write your nice, human-friendly methods, .NET Source Generators spin out the glue: handler functions, deserializers, and the bits needed to make Lambda “just work.” Even the CloudFormation serverless template is piped out. Curious? Go peek at the generated code or template if you like, but you rarely need to touch them.&lt;/p&gt;
&lt;h2 id=&quot;aspire-and-the-local-feedback-feedback-loop&quot;&gt;Aspire and the Local Feedback Feedback Loop&lt;/h2&gt;
&lt;p&gt;Local testing is where most serverless enthusiasm dies. Mocking infrastructure, wrangling function URLs, and staring at inscrutable errors is the norm. But this new workflow changes that equation.&lt;/p&gt;
&lt;p&gt;.NET Aspire’s &lt;code&gt;Aspire.Hosting.AWS&lt;/code&gt; package puts your Lambda in a local development harness. You can spin up everything with:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; builder&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; DistributedApplication&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;CreateBuilder&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; getRootFunction&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; builder&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddAWSLambdaFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Projects&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaAnnotationsDemo&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;GetRoot&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;    lambdaHandler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;LambdaAnnotationsDemo::LambdaAnnotationsDemo.Functions_GetRoot_Generated::GetRoot&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; getItemsFunction&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; builder&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddAWSLambdaFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Projects&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaAnnotationsDemo&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;GetItems&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;    lambdaHandler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;LambdaAnnotationsDemo::LambdaAnnotationsDemo.Functions_GetItems_Generated::GetItems&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; getItemFunction&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; builder&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddAWSLambdaFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Projects&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaAnnotationsDemo&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;GetItem&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;    lambdaHandler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;LambdaAnnotationsDemo::LambdaAnnotationsDemo.Functions_GetItem_Generated::GetItem&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; createItemFunction&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; builder&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddAWSLambdaFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Projects&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaAnnotationsDemo&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;CreateItem&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;    lambdaHandler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;LambdaAnnotationsDemo::LambdaAnnotationsDemo.Functions_CreateItem_Generated::CreateItem&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;builder&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddAWSAPIGatewayEmulator&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;APIGatewayEmulator&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Aspire&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Hosting&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;AWS&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Lambda&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;APIGatewayType&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;HttpV2&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WithReference&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;getRootFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Method&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WithReference&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;getItemsFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Method&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;/items&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WithReference&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;getItemFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Method&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;/items/{id}&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WithReference&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;createItemFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Method&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Post&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;/items&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;builder&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Build&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Run&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fire up Aspire locally, and you’ll get a dashboard showing your Lambda functions and an API Gateway emulator. Hit endpoints; tweak methods; debug as you would a regular web app. Not only does this save hours of frustration, it returns control to the engineer—no more blind deployment-faith.&lt;/p&gt;
&lt;p&gt;And when it’s time to ship, toss in a SAM template or the generated CloudFormation and deploy straight to AWS, no translation layer needed.&lt;/p&gt;
&lt;h2 id=&quot;evolving-with-minimal-friction&quot;&gt;Evolving with Minimal Friction&lt;/h2&gt;
&lt;p&gt;Here’s where it all pays off. You need to evolve your API: add a &lt;code&gt;DELETE&lt;/code&gt; endpoint, accept new parameters, or branch out to complex workflows. You don’t pay the serverless tax anymore. Just graft on another method, update the annotations, and you’re done.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LambdaFunction&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;HttpApi&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(HttpMethod &lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;DELETE&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, Path &lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;/product/{id}&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; DeleteProduct&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;Deleted product &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’ve maintained a direct line between engineering intent and cloud-native result. Plus, performance is up-to-date with .NET 10—so you’re not losing anything by moving serverless.&lt;/p&gt;
&lt;h2 id=&quot;closing-the-gap-between-api-imagination-and-reality&quot;&gt;Closing the Gap Between API Imagination and Reality&lt;/h2&gt;
&lt;p&gt;The part that engineers really care about—in my experience, at least—is flow. Not the meditative “in the zone” flow, but the deterministic, reproducible, low-surprise flow from business need to delivered feature. The new .NET serverless story, rooted in familiar ASP.NET paradigms, finally honors that.&lt;/p&gt;
&lt;p&gt;Yes, serverless is still evolving, and yes, debugging distributed systems remains a challenge. But today you can build production-grade .NET APIs for Lambda without putting on a different hat, learning a new language, or sacrificing codebase integrity. There’s an elegance to that—a closing of a tradeoff we’ve carried too long.&lt;/p&gt;
&lt;p&gt;If you’ve been hesitating to bring your .NET team into serverless, now’s the time: try building that next microservice the Aspire/Lambda way, and notice how little you have to re-train yourself. You might be surprised how much of your classic ASP.NET sensibility is preserved in the cloud.&lt;/p&gt;
&lt;p&gt;Want to see this in action—code and all? Check out the video version of this blog post &lt;a href=&quot;https://youtu.be/va100QlU2Vs&quot;&gt;on YouTube&lt;/a&gt;.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>On AI &amp; Creativity</title><link>https://blog.jameseastham.co.uk/blog/2025-12-12-on-ai-and-creativity/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/2025-12-12-on-ai-and-creativity/</guid><description>AI is here to stay, but what does that mean for the future of any industry that is creative? Whether that be software development, music, art or film. I don&apos;t have the answer, but I have thoughts.</description><pubDate>Fri, 12 Dec 2025 14:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;I’ve always written to help myself think, and I thought it may be interesting to share those thoughts with the world. This post was written in a single stream of consciousness with very little editing.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I love going to watch classical music. Listening to such a large group of people come together playing in such perfect harmony to create music is a sight I think everyone should witness at least once. Last time I attended, I tried to think more deeply about what it was I enjoyed so much. A thought planted whilst my wife and I were chatting about AI.&lt;/p&gt;
&lt;p&gt;When I really boil it down, the reason I love classical music is partly because it just sounds great on the ears. But also, and I think a bigger reason, is the amount of work each individual musician has put in to get to where they are on that stage. The inevitable failures, the challenges, the hours and hours of practice. That’s all paid off and there they are on a stage.&lt;/p&gt;
&lt;p&gt;If you look further back to the composers who wrote many of the great symphonies. I mean Beethoven was deaf, yet still managed to compose some of the greatest pieces of classical music that exist today.&lt;/p&gt;
&lt;p&gt;The humanness adds an extra dimension to almost all things we’d consider creative.&lt;/p&gt;
&lt;p&gt;## So how does this relate to AI?&lt;/p&gt;
&lt;p&gt;Seemingly, the problems AI companies are trying to target first are the creative ones. Disney selling the rights to their characters to Sora, Spotify generating their own AI music and flooding playlists with it. Nowadays, anyone has art/film/music at their fingertips. Just a prompt away.&lt;/p&gt;
&lt;p&gt;And when you think about it, this makes sense. I love this article and how it refers to LLM’s as a &lt;a href=&quot;https://www.experimental-history.com/p/bag-of-words-have-mercy-on-us&quot;&gt;bag of words&lt;/a&gt;. Without knowing the details of what data AI companies use to train their LLM’s, I would assume a lot of the words in the bag are from films, music, television and books. There is a lot of reference data, which makes generating stuff easy.&lt;/p&gt;
&lt;p&gt;When you compare that to science, as the &lt;a href=&quot;https://www.experimental-history.com/p/bag-of-words-have-mercy-on-us&quot;&gt;bag of words&lt;/a&gt; post does, things are a little different. Most groundbreaking science, by it’s very nature, is stuff that hasn’t been done before. That makes the bag of words pretty shit. There aren’t many words in the bag to describe something that is brand new.&lt;/p&gt;
&lt;p&gt;So whilst an AI could generate a bunch of low quality studies, repeating things that have already happened, I’m not convinced in it’s current form it could do anything new and novel. That’s just not how the tools work.&lt;/p&gt;
&lt;p&gt;All of this does beg the question though, what exactly is creativity?&lt;/p&gt;
&lt;h2 id=&quot;what-is-creativity&quot;&gt;What is creativity?&lt;/h2&gt;
&lt;p&gt;In all of the above; classical music, film, science, where exactly is the creativity? Which specific piece of it is creative?&lt;/p&gt;
&lt;p&gt;I was chatting to someone at a conference recently and a family member of their’s was an artist. And one of the things the artist used to do was take paint and throw it in the air above a canvas. Wherever the paint landed was how the piece started. The act of doing that seems pretty creative. But is that too dissimilar for having the seed of an idea and asking an AI to continue from there.&lt;/p&gt;
&lt;p&gt;This is where I get conflicted. Very conflicted. And I don’t know, even for myself in my day to day, where the right place to draw the line is. When does creativity, humanness, turn into AI generated slop. To be able to type a prompt into an AI service, you need to have the idea in the first place. Is that not creative? You have the idea, but you don’t have the skill to create the end product.&lt;/p&gt;
&lt;p&gt;I feel this conflict deeply when I start to relate these same ideas to software development.&lt;/p&gt;
&lt;p&gt;I’ve always been a backend developer, and I’m dreadful at anything frontend or UX related. I know enough to be dangerous, but not enough to create quality front-end experiences.&lt;/p&gt;
&lt;p&gt;Now I have a tool at my fingertips that allows me to think of an idea, code the backend and generate a passable frontend layer that is 10x better than anything I could have created myself.&lt;/p&gt;
&lt;p&gt;The creativity is in the idea, and it feels great to generate functional applications quickly. But does that diminish the hours and hours and hours of time others have put in to becoming great frontend engineers?&lt;/p&gt;
&lt;p&gt;Quick sidebar, the one relatively large frontend codebase I’ve used an AI to generate become an absolute un-maintainable hellscape after a month or two of work and adding new features. Probably due to my lack of skills on &lt;em&gt;how&lt;/em&gt; to build quality frontend applications.&lt;/p&gt;
&lt;h2 id=&quot;creativity-in-software-development&quot;&gt;Creativity in software development&lt;/h2&gt;
&lt;p&gt;So what is the creative part of software development? For me, software exists to solve a problem. To make someone’s else life easier, faster, better or more efficient. If you’re building software that isn’t doing that then what is the point in building it.&lt;/p&gt;
&lt;p&gt;The creative part, is solving the problem. Is figuring out a new or novel solution to meet your users needs. Whether that’s the specific needs of the user, or the fact you’re user traffic has increased 100x and you need to find a way to scale it.&lt;/p&gt;
&lt;p&gt;Most software systems I’ve ever worked on are snowflakes. We talk about microservices, or serverless, or event-driven architecture, but even systems that follow these patterns are unique. Different programming languages, different tools, different stacks, different business conditions, different leadership styles, different team structures. All these things come together to build software.&lt;/p&gt;
&lt;p&gt;All of these things, make your system unique. It might be similar to other systems, but without a doubt it’s unique.&lt;/p&gt;
&lt;p&gt;And this is where I think things start to get interesting with AI.&lt;/p&gt;
&lt;p&gt;Because whilst your system might be unique to mine, there are some similarities. We’ll both have tasks we need to do that are repetitive and tedious.&lt;/p&gt;
&lt;p&gt;“Oh crap, I need to add a new property to the class and then make the same change in 10 separate code files”.&lt;/p&gt;
&lt;p&gt;“We’ve added this one API route, I need to scaffold 20 others in the same fashion”&lt;/p&gt;
&lt;p&gt;“I’ve got an API with 30 routes, now I need to generate an OpenAPI spec to document it”&lt;/p&gt;
&lt;p&gt;These repetitive, tedious tasks is where I believe AI coding assistants shine. I can give them clear guardrails, go off and do this things.&lt;/p&gt;
&lt;p&gt;But the stuff that makes your software unique, the stuff that solves your users needs in a new and novel way. The creativity that you as a human, with all your experience, your 3am pagers, your big wins and terrible losses. That creativity to solve new and novel problems in new and novel ways.&lt;/p&gt;
&lt;p&gt;The bag of words ain’t got a chance.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>The Simplest Way to Deploy Containerized Apps on Azure in 2025</title><link>https://blog.jameseastham.co.uk/blog/simplest-way-deploy-to-azure/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/simplest-way-deploy-to-azure/</guid><description>This blog post covers how to deploy containerized application in a serverless way to Azure in 2025 using Azure Container Apps.</description><pubDate>Fri, 17 Jan 2025 13:30:03 GMT</pubDate><content:encoded>&lt;p&gt;Picture this: You’ve just built the first version of your containerized backend application. The code is clean, the architecture is solid, and everything runs on your machine. It’s simple, it’s portable and it meets the requirements. And then comes the question… How do you get that application to your users?&lt;/p&gt;
&lt;p&gt;If you’re like most developers, you want to focus on building features, not managing/operating/security/battling infrastructure. You’ve heard about Kubernetes, but honestly, you’d rather not deal with its complexity right now. You just want your container to run reliably in the cloud. Sound familiar?&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://azure.microsoft.com/en-us/products/container-apps&quot;&gt;Azure Container Apps&lt;/a&gt; - probably my favourite service across all of the cloud providers. Let me show you why it’s become my go-to solution for deploying containerized applications, and how you can get started with it today. Using everyone’s favourite pizza restaurant - &lt;a href=&quot;https://github.com/jeastham1993/PlantBasedPizza&quot;&gt;PlantBasedPizza&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-makes-azure-container-apps-special&quot;&gt;What Makes Azure Container Apps Special?&lt;/h2&gt;
&lt;p&gt;At its core, Azure Container Apps is a serverless platform for running containers. While it’s built on top of Kubernetes, you don’t need to know anything about Kubernetes to use it effectively. Think of it as getting all the benefits of a modern container platform without the operational overhead.&lt;/p&gt;
&lt;p&gt;Container Apps is incredibly simple. There are only two concepts at the core of all applications:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Container Apps Environment - Think of this as your deployment space. It could be your dev, staging, or production environment.&lt;/li&gt;
&lt;li&gt;Container Apps - These are your actual applications, running as containers within the environment.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it. No nodes to manage, no clusters to configure, no complex networking to set up. Just your code, in a container, running in the cloud.&lt;/p&gt;
&lt;p&gt;Getting an application running is remarkably straightforward. You only need to specify:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;How much CPU and memory your app needs&lt;/li&gt;
&lt;li&gt;Whether you want public access (ingress)&lt;/li&gt;
&lt;li&gt;Your container image&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it. No load balancers to configure, no clusters to manage, no node pools to size. Container Apps handles all of that for you.&lt;/p&gt;
&lt;p&gt;And whilst things start simple, you can get more complex if needed. For example, you can define &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/container-apps/scale-app?pivots=azure-cli&quot;&gt;auto-scaling rules&lt;/a&gt;. Scale rules can be based on HTTP, TCP, custom data (CPU/memory) and even other Azure services like Azure Service Bus or Azure Event Hubs.&lt;/p&gt;
&lt;p&gt;One of my favoutire features is the native integration with &lt;a href=&quot;https://dapr.io/&quot;&gt;Dapr (Distributed Application Runtime)&lt;/a&gt;. With Dapr enabled, you get:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Service-to-service invocation using just application names&lt;/li&gt;
&lt;li&gt;Built-in pub/sub capabilities&lt;/li&gt;
&lt;li&gt;State management&lt;/li&gt;
&lt;li&gt;Secrets management&lt;/li&gt;
&lt;li&gt;And so much more, all without changing your application code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, if you have two services – &lt;code&gt;order-service&lt;/code&gt; and &lt;code&gt;payment-service&lt;/code&gt; – they can communicate simply by using each other’s names. No need to manage URLs, service discovery, or retry logic. Honestly, if you’ve not come across Dapr I’d highly recommend checking it out.&lt;/p&gt;
&lt;p&gt;Perhaps one of the most underappreciated aspects is that Container Apps provides a nice off-ramp. Since it’s built on Kubernetes, if you ever outgrow its capabilities, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Migrate to Azure Kubernetes Service (AKS)&lt;/li&gt;
&lt;li&gt;Keep your existing container configurations&lt;/li&gt;
&lt;li&gt;Maintain similar deployment patterns&lt;/li&gt;
&lt;li&gt;Preserve your development workflows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You would still need to actually build the Kubernetes infrastructure, but because under the hood ACA is using open source tooling it’s a relatively safe choice for growing applications – you can start simple and scale up without needing to completely rearchitect your system. And if you do ever need Kubernetes &lt;em&gt;(you probably don’t)&lt;/em&gt; you have an off ramp.&lt;/p&gt;
&lt;h2 id=&quot;deploying-your-first-container-app&quot;&gt;Deploying Your First Container App&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=tAaRX6wOQn4&quot;&gt;&lt;img src=&quot;https://img.youtube.com/vi/tAaRX6wOQn4/0.jpg&quot; alt=&quot;Link to video on YouTube for deploying a container app&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let’s get practical. Instead of clicking around in the Azure portal (it’s 2025, after all), we’ll use infrastructure as code. Personally, I’m a big fan of using the same language to define my infrastructure as my application code. Which makes &lt;a href=&quot;https://www.pulumi.com/&quot;&gt;Pulumi&lt;/a&gt; an excellent choice for defining and deploying applications to Azure.&lt;/p&gt;
&lt;p&gt;Look just how simple it is to define a container app on Azure:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; environment&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ManagedEnvironment&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;pizza-prod-env&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ManagedEnvironmentArgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    ResourceGroupName&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; resourceGroup&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Location&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; location&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    EnvironmentName&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;production&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    SkuName&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;Consumption&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; app&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ContainerApp&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;pizza-backend&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ContainerAppArgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    ResourceGroupName&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; resourceGroup&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    ContainerAppEnvironmentId&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; environment&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Id&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Configuration&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ConfigurationArgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        Ingress&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IngressArgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;            External&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;            TargetPort&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 8080&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// The port on your local container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;            Traffic&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TrafficWeightArgs&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;                Weight&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;                LatestRevision&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    Template&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TemplateArgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        Containers&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ContainerArgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;                Name&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;pizza-api&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;                Image&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;your-registry/pizza-api:latest&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;                Resources&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ContainerResourcesArgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;                    CPU&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 0.5&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;                    Memory&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;1Gi&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code creates everything you need to run your application. Let’s break down what’s happening:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, we create a Container Apps Environment - this is where your apps will live&lt;/li&gt;
&lt;li&gt;Then, we create the Container App itself, specifying:
&lt;ul&gt;
&lt;li&gt;Basic resource requirements (CPU and memory)&lt;/li&gt;
&lt;li&gt;The container image to use&lt;/li&gt;
&lt;li&gt;Whether it should be publicly accessible (external ingress)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;real-world-considerations&quot;&gt;Real-World Considerations&lt;/h2&gt;
&lt;p&gt;Of course, real applications need more than just basic deployment. Azure Container Apps has you covered there too. You can easily:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scale based on HTTP traffic or custom metrics&lt;/li&gt;
&lt;li&gt;Set up authentication and authorization&lt;/li&gt;
&lt;li&gt;Use managed identities for secure access to other Azure services&lt;/li&gt;
&lt;li&gt;Deploy multiple containers as sidecars (great for logging agents or service meshes)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, adding a DataDog monitoring sidecar is as simple as adding another container to your template:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Containers&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    // Your main application container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ContainerArgs&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;/* ... */&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    // DataDog sidecar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ContainerArgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        Name&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;datadog-agent&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        Image&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;datadog/agent:latest&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        Environment&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;EnvironmentVarArgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;                Name&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;DD_API_KEY&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;                SecretRef&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;dd-api-key&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Ready to try it yourself? Here’s what you need:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A containerized application (if you don’t have one, you can use the example from PlantBasedPizza)&lt;/li&gt;
&lt;li&gt;An Azure subscription&lt;/li&gt;
&lt;li&gt;Pulumi CLI installed (or if Terraform is your jam, then a &lt;a href=&quot;https://github.com/jeastham1993/PlantBasedPizza/tree/microservices-module-1&quot;&gt;Terraform example&lt;/a&gt; is available in GitHub as well)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The full sample code, including a complete pizza ordering backend, is available in my &lt;a href=&quot;https://github.com/jeastham1993/PlantBasedPizza/tree/microservices-module-1&quot;&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-should-you-care&quot;&gt;Why Should You Care?&lt;/h2&gt;
&lt;p&gt;The cloud shouldn’t be complicated. Azure Container Apps gives you a production-ready platform for running containerized applications without the complexity of managing Kubernetes directly. It’s perfect if you want to focus on building features rather than managing infrastructure.&lt;/p&gt;
&lt;p&gt;Best of all, if you do eventually need more control or want to migrate to a full Kubernetes cluster &lt;em&gt;(you still probably shouldn’t)&lt;/em&gt;, you’re already using compatible technologies.&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next?&lt;/h2&gt;
&lt;p&gt;Start small. Take a simple containerized application and deploy it using the code samples above. Once you’re comfortable with the basics, you can explore more advanced features like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dapr integration for microservices communication&lt;/li&gt;
&lt;li&gt;Auto-scaling rules&lt;/li&gt;
&lt;li&gt;Virtual network integration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Remember, the goal is to keep things simple while maintaining the flexibility to grow as your needs evolve.&lt;/p&gt;
&lt;p&gt;Give it a try, and let me know how it goes! Drop a comment below or reach out on socials if you have any questions.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>On Choosing Your Complexity</title><link>https://blog.jameseastham.co.uk/blog/on-choosing-your-complexity/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/on-choosing-your-complexity/</guid><description>Software is complex, but you can choose your complexity. This post explores the things you do have control over, and the things you don&apos;t.</description><pubDate>Mon, 16 Dec 2024 19:47:03 GMT</pubDate><content:encoded>&lt;p&gt;Software is complex. I don’t think that’s a controversial statement. Building, testing, observing, scaling, failing, evolving. And that’s before you try to understand what it is your users want the system to do.&lt;/p&gt;
&lt;p&gt;At times, it can be a bit demoralizing can’t it? Constantly fighting against this ever changing, ever growing challenge of a system that is getting more and more complex. You think back to the days when you built a “hello world” application to learn a new concept and you wonder where all this complexity came from.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it’s worth it in the end because once you get there, you can move mountains. - &lt;em&gt;Steve Jobs&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Reading Steve Jobs’ biography (which is an excellent read by the way) one of my biggest takeaways is simplicity. One of the reasons Apple became so successful is the relentless focus on simplicity.&lt;/p&gt;
&lt;p&gt;Take the well-told story of Job’s second coming at Apple. On his return, the product lines had grown massively. To the point Apple’s own teams couldn’t explain which Mac to pick. Internally, teams thought they were meeting a user needs when actually they were confusing customers with so many choices.&lt;/p&gt;
&lt;p&gt;When Job’s came back, he changed the entire product line to just have 4 products. Yep, just 4. 2 desktop computers and 2 portable devices. An obvious example of simplification, but it had the right effect.&lt;/p&gt;
&lt;p&gt;When you’re trying to change an entire industry, you are already dealing with lots of complexity. Changing human behaviors, introducing a new way of interacting with technology. This is &lt;strong&gt;essential complexity&lt;/strong&gt;. Introducing 10x more product lines than you actually need, that is a form of &lt;strong&gt;accidental complexity&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;What does this mean for you dear reader? Many of you will be working on new systems. New systems that will require a change in human behavior. Many of you are likely operating in a highly complex business domain where the problem space itself is highly complex.&lt;/p&gt;
&lt;p&gt;Every single software system that exists has a certain level of &lt;strong&gt;essential complexity&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Take &lt;a href=&quot;https://github.com/jeastham1993/PlantBasedPizza&quot;&gt;Plant Based Pizza&lt;/a&gt;, the backend for a pizza restaurant. Whilst not the most complex of domains, there is still a decent amount of complexity to think about. Taking orders, managing stock, managing staff, taking payments, refunding payments, preparing orders, organizing delivery drivers and getting the order delivered to the correct address.&lt;/p&gt;
&lt;p&gt;And that’s just considering the happy path. What if a payment fails? Or an order is ready but there aren’t any delivery drivers available.&lt;/p&gt;
&lt;p&gt;Think about the systems you are working on, they will inevitably have their own essential complexity.&lt;/p&gt;
&lt;p&gt;Unfortunately for us, this complexity can’t be removed. Much like Apple trying to change an entire industry, you can’t get around this complexity. Trying to “simplify” this complexity can seem like a challenge.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Accidental complexity&lt;/strong&gt; though, that’s something you do have some agency over.&lt;/p&gt;
&lt;h2 id=&quot;accidental-complexity&quot;&gt;Accidental Complexity&lt;/h2&gt;
&lt;p&gt;Accidental complexity is the complexity that comes from the choices you make. The complexity that &lt;strong&gt;you&lt;/strong&gt; (or your company) has control over.&lt;/p&gt;
&lt;p&gt;Every technology choice you make will change the amount of accidental complexity of your system.&lt;/p&gt;
&lt;p&gt;When &lt;a href=&quot;https://github.com/jeastham1993/PlantBasedPizza&quot;&gt;Plant Based Pizza&lt;/a&gt; first started, they focused on delivering value quickly. At that time, there was a team of 5 building the backend. They built a monolithic application with a Postgres database to support all the different business use cases.&lt;/p&gt;
&lt;p&gt;A single running process and a simple, flexible and well understood database technology == simplicity!&lt;/p&gt;
&lt;p&gt;Of course, once they built the application they needed to run it somewhere. One of the team had been reading about Kubernetes recently and got the rest of the team incredibly excited about building a shiny new Kubernetes cluster.&lt;/p&gt;
&lt;p&gt;They created a cluster, deployed some virtual machines instances as the underlying compute and used a managed database service for providing the Postgres functionality. Great, we are live.&lt;/p&gt;
&lt;p&gt;This isn’t the part of the story where I shit on Kubernetes. It’s merely an example of the complexity you’ve just accidentally introduced into your system. Think about all the things you need to think about running a Kubernetes cluster:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scaling nodes&lt;/li&gt;
&lt;li&gt;Operating nodes&lt;/li&gt;
&lt;li&gt;Securing nodes&lt;/li&gt;
&lt;li&gt;Dealing with node failures&lt;/li&gt;
&lt;li&gt;Upgrading the cluster&lt;/li&gt;
&lt;li&gt;Securing the cluster&lt;/li&gt;
&lt;li&gt;Dealing with the cluster failing&lt;/li&gt;
&lt;li&gt;Scaling your application&lt;/li&gt;
&lt;li&gt;Dealing with application failures&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s before you consider the various 3rd party tools you’ll need to deploy inside the cluster and keep up to date.&lt;/p&gt;
&lt;p&gt;Let’s consider an alternative universe where the team made a different decision.&lt;/p&gt;
&lt;p&gt;The team still packaged the monolithic backend application as a container image, and still used a Postgres database. They made that decision for simplicity (containers are well understood) and portability (containers can run anywhere, as can Postgres).&lt;/p&gt;
&lt;p&gt;Instead of spinning up a Kubernetes cluster though, they used a managed container orchestrator. Something like Amazon ECS (with Fargate), Azure Container Apps or Google Cloud Run. They kept the Postgres database running in a managed cloud database service.&lt;/p&gt;
&lt;p&gt;Let’s look at the complexity you’ve just introduced:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scaling your application&lt;/li&gt;
&lt;li&gt;Dealing with application failures&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A shorter list, right? Using a managed container orchestrator means you shift a whole bunch of that accidental complexity on to the cloud provider. Operating nodes? Operating clusters? Dealing with node failures? That’s the cloud providers responsibility now.&lt;/p&gt;
&lt;p&gt;There’s a trade off here with cost of course, and I talked about that recently in this post &lt;a href=&quot;./on-factors-of-modern-compute.md&quot;&gt;on the factors of modern compute&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;Continuing this tale, we fast forward 12 months. Plant Based Pizza has grown, and there are now 50 developers across 5 different teams. All teams are still contributing to that same monolithic code base, and are getting in each others way.&lt;/p&gt;
&lt;p&gt;This is a form of accidental complexity! The complexity that comes from the decision to grow teams. Complexity you now need to deal with.&lt;/p&gt;
&lt;p&gt;Microservices are a reaction to organization challenges. Microservices are a solution to a socio-technical problem. They aren’t a solution to a technology problem.&lt;/p&gt;
&lt;p&gt;So the Plant Based Pizza team decides to start to break their application down into microservices. As you might expect, microservices introduce their own complexity. And believe me, microservices introduce a lot of technology complexity.&lt;/p&gt;
&lt;p&gt;At this point, there is no good reason to change the complexity of your underlying compute. You are already introducing enough additional complexity by choosing microservices, introducing another layer of infrastructure complexity probably won’t help you too much.&lt;/p&gt;
&lt;p&gt;Speeding forward in time again, Plant Based Pizza has now been refactored to microservices. These microservices are communicating with asynchronous events to make them as loosely coupled as possible. And you’re still running the applications (packaged as containers) on serverless compute. You still don’t have a good reason to introduce the complexity of Kubernetes.&lt;/p&gt;
&lt;p&gt;What accidental complexity does the system have?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scaling the applications&lt;/li&gt;
&lt;li&gt;Dealing with application failures&lt;/li&gt;
&lt;li&gt;Eventual consistency across different microservices&lt;/li&gt;
&lt;li&gt;Service to service communication&lt;/li&gt;
&lt;li&gt;Observability (it’s hard in asynchronous systems)&lt;/li&gt;
&lt;li&gt;Governance and evolving the system safely&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Slightly more complexity, but still not crazy amounts right? And all this complexity is something you can have direct control over as a developer.&lt;/p&gt;
&lt;p&gt;If you choose to run your application on Kubernetes you still have this complexity to deal with, as well as all the complexities that come from Kubernetes.&lt;/p&gt;
&lt;p&gt;Again, this isn’t a post written to bash Kubernetes. It has a place in the world. But you probably don’t need it for your applications.&lt;/p&gt;
&lt;p&gt;And if you are building with Kubernetes, you can still apply this lens of accidental complexity. Does every single developer inside your company need to understand Kubernetes? Do they need to understand Helm charts and YAML files. Or can you build your Kubernetes cluster in a way that means developers only care about shipping container images. This is, of course, platform engineering.&lt;/p&gt;
&lt;p&gt;When I was at AWS I worked with a company (that I can’t name) doing this. They were building an abstraction layer on top of Kubernetes so that developers could just ship container images and not worry about anything else. To add complexity, this abstraction layer also spanned multiple cloud providers.&lt;/p&gt;
&lt;p&gt;Whilst it was an interesting project to work on, it wasn’t for the business. They had put an insane amount of money, developer time and operational responsibility into building a service that wasn’t even nearly as feature complete as Amazon ECS or Azure Container Apps. They even had a side by side comparison chart and the custom built service wasn’t anywhere near.&lt;/p&gt;
&lt;p&gt;All of that, to deploy business applications… To put it bluntly what a massive waste of time and effort.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You need Kubernetes if your ability to dynamically scale and manage infrastructure is a core differentiator for your business.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The takeaway from this rambling post is to think about the decisions you make and the complexity that introduces.&lt;/p&gt;
&lt;p&gt;Focus on building stateless, portable, containerized applications. Focus on structuring your application code to separate infrastructure concerns from business logic (ports and adapters style). Focus on shipping those applications in an operationally light way as possible.&lt;/p&gt;
&lt;p&gt;Reduce your operational/infrastructure complexity by adopting managed platforms and shifting that responsibility onto the cloud provider. Cost is of course a consideration here. The line item cost of running Fargate is more than a comparable EC2 instance. But that doesn’t take into account the human cost required to run EC2.&lt;/p&gt;
&lt;p&gt;You can see this line of thinking in action with the fact all the cloud providers now have some form of ‘Kubernetes auto’. Where you can run Kubernetes, and then pay your cloud provider extra to take a chunk of the operational overhead.&lt;/p&gt;
&lt;p&gt;If you focus on stateless, portable containers this compute conversation becomes largely irrelevant. Run your application in a place that makes sense right now, and you are ready to deal with future changes.&lt;/p&gt;
&lt;p&gt;As a thought exercise, think about the accidental complexity you have in your system today? What complexity are you dealing with that isn’t related to the business problem you are trying to solve. And importantly, what could you do to reduce it?&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>On Patterns of Modern App Development</title><link>https://blog.jameseastham.co.uk/blog/on-patterns-of-modern-apps/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/on-patterns-of-modern-apps/</guid><description>What makes up a modern application? What components do you need to think about and how do you architect them together?</description><pubDate>Wed, 20 Nov 2024 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;We build modern applications on common building blocks. Applications may use one or all of the building blocks. They are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User-facing applications&lt;/li&gt;
&lt;li&gt;Background applications&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;li&gt;Integration&lt;/li&gt;
&lt;li&gt;Caches&lt;/li&gt;
&lt;li&gt;Observability&lt;/li&gt;
&lt;li&gt;Service-to-service communication&lt;/li&gt;
&lt;li&gt;Orchestration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This isn’t an exhaustive list. But it gives us a set of building blocks, first principles, that form the basis for thinking about modern applications.&lt;/p&gt;
&lt;h3 id=&quot;user-facing-applications&quot;&gt;User-facing applications&lt;/h3&gt;
&lt;p&gt;The first, and probably most obvious, is the web application. I use the term application loosely here. It could be an API, a server-side rendered web app, or a frontend. The critical thing to remember is that someone external consumes these applications. That external person could be another team inside your organisation or someone browsing your site on their mobile.&lt;/p&gt;
&lt;p&gt;User-facing applications, regardless of who the user is, have a set of common characteristics. User-facing applications need to be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fast&lt;/li&gt;
&lt;li&gt;resilient&lt;/li&gt;
&lt;li&gt;exactly where I (the caller) expect them to be&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First, web-facing applications need to be performant. In my experience, users are always unhappy. Things could always be more performant. An application’s performance can directly impact a user’s job performance and satisfaction. If you’ve used Salesforce, you’ll know exactly what I mean.&lt;/p&gt;
&lt;p&gt;The second and third options in the list are related. In addition to being fast, if I’m a user calling a web application, I want it to be there and to work. ‘Working’ is a broad term, and what working means will depend on the application, the context, and the use case (&lt;em&gt;a rarely called non-critical service can probably accept some downtime&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;But inside whatever the SLA you’ve set, you want the web app you’re calling to work and to exist behind the DNS name you’re calling to access it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“I’m happy with this slow service that only works some of the time” - &lt;em&gt;No user ever&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;User-facing applications use synchronous communication. This article would grow exponentially if I discussed the ideas of coupling, so let’s leave it at that.&lt;/p&gt;
&lt;h3 id=&quot;background-applications&quot;&gt;Background applications&lt;/h3&gt;
&lt;p&gt;I’m differentiating a background application as an application that doesn’t have another user (remember, the user could be a human or another service) accessing it synchronously. A background application reacts to messages coming from an external location.&lt;/p&gt;
&lt;p&gt;Background applications will run, wait for a message to arrive, and then pick it up and process it once a message does arrive. You don’t want your application sitting there idle, consuming resources and costing money when there is no work to do. I’d argue the most important characteristic of a background service is its ability to adjust itself according to throughput—in both directions.&lt;/p&gt;
&lt;p&gt;You don’t want to worry about your application if your message volumes increase, and if they decrease, you want your applications to scale back automatically.&lt;/p&gt;
&lt;p&gt;Idempotency is also incredibly important. Most messaging services guarantee ‘at least once’ delivery. Some give you the option to switch to guaranteed one-time delivery, but with that, you lose throughput. Honestly, even if you use a messaging system that supports guaranteed one-time delivery, &lt;strong&gt;YOU STILL NEED TO THINK ABOUT IDEMPOTENCY&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If you aren’t familiar, idempotency is the idea that the outcome should be the same if the same message/request hits the same service multiple times. If I receive a &lt;code&gt;TakePayment&lt;/code&gt; request for order &lt;code&gt;12345&lt;/code&gt;, and then I receive the same request a minute later, you don’t want to take the payment again. Of course, this would also apply to user-facing applications.&lt;/p&gt;
&lt;p&gt;As a developer, these are the two components you have direct control over. You can write code that addresses some of these challenges. But the code you write isn’t the only thing that makes up your application.&lt;/p&gt;
&lt;h3 id=&quot;storage&quot;&gt;Storage&lt;/h3&gt;
&lt;p&gt;When you store data, you want it to be there again later. Whether that’s file storage, blog storage or more typical relational databases, the ability to persist state is an important part of almost every application, particularly if you are building your application layer to be completely stateless (&lt;em&gt;hint, you probably should be&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;What that storage looks like would change from system to system, but you’ll likely need to persist things.&lt;/p&gt;
&lt;h3 id=&quot;integration&quot;&gt;Integration&lt;/h3&gt;
&lt;p&gt;Unless you’re building a monolith, things need to communicate. Even if you are building a monolith, you may still use queues to offload some processing from your main user flow. You can still use asynchronous processing inside a monolithic application.&lt;/p&gt;
&lt;p&gt;That said, messaging and integration are more common in a microservices architecture. If you’re a developer working on a single microservice, it’s not your single microservice that makes up ‘the system’. All the individual services work together and form something greater than their parts: &lt;strong&gt;the system&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For that to work, your components need to integrate, whether synchronous or asynchronous. Systems need to talk!&lt;/p&gt;
&lt;h3 id=&quot;caching&quot;&gt;Caching&lt;/h3&gt;
&lt;p&gt;As systems grow bigger and more distributed, data spreads across multiple backend services. Or your users may complain that your app needs to be faster. Caching is one solution to that problem.&lt;/p&gt;
&lt;p&gt;Caches aren’t a long-term storage mechanism. Hence, they’re being grouped separately, but they are an excellent lever to pull to increase your app’s performance. A cache could be something more traditional like Redis or an in-memory state you hold inside your application. Think of a cache as an extremely fast temporary store.&lt;/p&gt;
&lt;p&gt;Caches bring about their own sets of challenges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When does something expire in the cache?&lt;/li&gt;
&lt;li&gt;How does the cache get updated?&lt;/li&gt;
&lt;li&gt;How do you deal with stale data that isn’t current but has yet to expire?&lt;/li&gt;
&lt;li&gt;How many cache hits/misses am I getting? Is this helping my system?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a bunch of questions you need to answer with caching. And if your cache isn’t set up correctly, it can &lt;strong&gt;add&lt;/strong&gt; latency to your system. It’s not a silver bullet but a core building block of modern distributed apps. &lt;em&gt;Hint: companies like &lt;a href=&quot;https://www.gomomento.com/&quot;&gt;Momento&lt;/a&gt; give you fully serverless caching&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;observability&quot;&gt;Observability&lt;/h3&gt;
&lt;p&gt;Observability should be number one. If you can’t understand what is happening inside your system, how can you possibly expect to fix a bug or make it better? Observability is the most important part of building modern applications. You need the ability to ask questions about your system to understand individual requests and the context around them. That should be where you start.&lt;/p&gt;
&lt;p&gt;Think about it. A product manager comes along and says the system needs to be faster. How do you find the bottleneck? The first-line support team calls you with an odd bug they can’t diagnose. How do you know where to start? You’ve added a cache to your system, and performance has worsened. Why?&lt;/p&gt;
&lt;p&gt;Observability helps you answer the questions. A good observability strategy should allow you to play detective and ask questions of your system that you didn’t know you needed to ask.&lt;/p&gt;
&lt;p&gt;There’s probably a whole other blog post on this… Stay tuned, or ya’know. You could subscribe…? :)&lt;/p&gt;
&lt;h3 id=&quot;orchestration&quot;&gt;Orchestration&lt;/h3&gt;
&lt;p&gt;The final one, which I wasn’t sure about including, is orchestration. You could replace the word orchestration with workflow. Software systems exist to solve problems, most of which are multi-step. If I order a pizza, software in the background is going to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check the stock&lt;/li&gt;
&lt;li&gt;Take the payment&lt;/li&gt;
&lt;li&gt;Send to the kitchen&lt;/li&gt;
&lt;li&gt;Wait for the kitchen to prepare the pizza&lt;/li&gt;
&lt;li&gt;Find a delivery driver&lt;/li&gt;
&lt;li&gt;Deliver the order&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Whether you’re building a monolith or distributed event-driven microservices, you’ll need to write some code somewhere in your code base to determine what happens next. After payment is taken, what do I do? If the payment fails, what do I do?&lt;/p&gt;
&lt;p&gt;That’s why I’ve included orchestration in this list. Your system is probably orchestrating something, even if you are not explicitly using an orchestrator.&lt;/p&gt;
&lt;p&gt;This gives us the building blocks—the overarching ‘patterns’ of modern apps, if you will. Inside each of these components, there is a range of options, services, and decisions. For the vast majority of use cases I’ve encountered in my career, you would benefit from trying to make each component as serverless as possible.&lt;/p&gt;
&lt;p&gt;But what does serverless even mean? (If you want to dive deeper into modern compute you &lt;a href=&quot;./on-factors-of-modern-compute.md&quot;&gt;might like this article&lt;/a&gt;).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There are almost definitely some things I have missed here, and I’d love to hear from you!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;serverless-what-does-it-even-mean&quot;&gt;Serverless? What does it even mean&lt;/h2&gt;
&lt;p&gt;Historically, serverless has been defined by a set of core principles. &lt;a href=&quot;https://gomomento.com&quot;&gt;Momento&lt;/a&gt; wrote a great article introducing the &lt;a href=&quot;https://www.gomomento.com/blog/fighting-off-fake-serverless-bandits-with-the-true-definition-of-serverless/&quot;&gt;Litmus Test for Serverless&lt;/a&gt;. For a service to be considered serverless it must:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Have nothing to provision or manage&lt;/li&gt;
&lt;li&gt;Usage-based pricing with no minimums&lt;/li&gt;
&lt;li&gt;Ready with a single API call&lt;/li&gt;
&lt;li&gt;No planned downtime&lt;/li&gt;
&lt;li&gt;No instances&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I like this definition, but I would add one caveat. Viewing serverless as ‘all or nothing’—either serverless or not—can remove some valuable services.&lt;/p&gt;
&lt;p&gt;Take a service like Azure Container Apps (ACA). ACA is a container orchestrator that provides an abstraction on top of Kubernetes. You can deploy an application by providing a container image, CPU/memory requirements and scaling behaviour if required. &lt;strong&gt;There is almost 0 operational overhead running an application this way&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Looking at the Litmus test, this meets the criteria of 1, 3, 4 and 5. 2 gives us nuance. An application running on ACA won’t automatically scale to zero; you can configure scaling rules, but it doesn’t ‘just happen’. When stopped, they don’t cost you anything. You pay only when your app is running. But your app is running &lt;em&gt;all the time&lt;/em&gt; even if no requests are coming in.&lt;/p&gt;
&lt;p&gt;This application is still serverless. No, it doesn’t automatically scale to zero. Yes, you would pay for the application running when no requests are coming in. &lt;strong&gt;But you can deploy an application with next to 0 operational overhead&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Serverless is a spectrum, not a binary decision. You can be more or less serverless based on the requirements of your application.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In &lt;a href=&quot;https://github.com/jeastham1993/patterns-of-modern-apps&quot;&gt;this repository&lt;/a&gt;, I demonstrate how to run modern web applications on various cloud providers with little to no operational overhead.&lt;/p&gt;
&lt;h3 id=&quot;what-does-it-mean-for-you&quot;&gt;What does it mean for you?&lt;/h3&gt;
&lt;p&gt;If you’re a developer, at least anything like me, you want to run your application with as little infrastructure worries as possible. &lt;em&gt;“Here’s my application. It needs this CPU and memory, scale it like this, and frankly, I don’t care about anything else.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If your company has invested time, energy, and money into building a Kubernetes platform, then great. That can &lt;em&gt;feel&lt;/em&gt; serverless to you as a developer; leverage it. This isn’t to say Kubernetes isn’t valuable—it very much is. But it’s valuable when your application needs it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If your ability to dynamically scale and manage infrastructure is a core differentiator for your business and your customers, great. Go for it. Otherwise, you don’t need Kubernetes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Are you training a machine learning model, doing heavy GPU computation, or ingesting dynamic/large amounts of data? Virtual machines and Kubernetes are probably useful.&lt;/p&gt;
&lt;p&gt;The conversation around managed services vs. Kubernetes becomes more interesting when you zoom out and look at the bigger picture. Does your organisation have an excellent reason to invest in building a Kubernetes platform (which is just rebuilding Cloud Run/Fargate/Container Apps)? If you have a good reason to do it (that isn’t CV-driven development), then great.&lt;/p&gt;
&lt;p&gt;Otherwise, use a managed serverless, be as serverless as possible, and build your application to keep you portable.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>On The Dimensions of Modern Compute</title><link>https://blog.jameseastham.co.uk/blog/on-factors-of-modern-compute/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/on-factors-of-modern-compute/</guid><description>Pulling together my thoughts on modern compute platforms, and the decisions and trade-offs you need to consider when choosing serverless, bare metal servers or anything in between.</description><pubDate>Wed, 13 Nov 2024 11:40:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;I gave a talk recently at &lt;a href=&quot;https://rustlab.it/&quot;&gt;RustLab&lt;/a&gt;. The talk focused on building with Rust &amp;amp; Serverless; a couple of slides related to this serverless spectrum triggered some discussion afterwards. This post is me pulling together some of these ideas and trying to make sense of them.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Serverless Is A Spectrum, Not A Binary Decision&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The limitations of Markdown don’t allow me to make that point any more strongly. When you choose the compute to run your application, you have a wide range of options, from bare metal instances running in a data centre to serverless functions and many steps in between.&lt;/p&gt;
&lt;p&gt;Boxing yourself into ‘serverless only’ or ‘Kubernetes only’ limits your options. Every organisation I’ve worked in has some use cases that better suit a long-running container and some use cases that suit a reactive style of computing.&lt;/p&gt;
&lt;p&gt;Of course, it’s possible to run long-running web apps on serverless functions and reactive compute on Kubernetes with services like KEDA. But is that what we want? Aren’t we just forcing square pegs into round holes?&lt;/p&gt;
&lt;p&gt;My mental model for compute is thinking about it as a spectrum. Where you choose to sit on that spectrum will depend entirely on what your application needs.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.jameseastham.co.uk/assets/blog/serverless-spectrum-ops.png&quot; alt=&quot;a spectrum displaying operational overhead on the far right and infrastructure flexibility on the left&quot;&gt;&lt;/p&gt;
&lt;p&gt;A spectrum is a much more interesting model for thinking about compute choices. Look at your application and its requirements, and then decide what is most important.&lt;/p&gt;
&lt;p&gt;Imagine for a moment that you’re building an app with an interface that serves web requests. Those web requests are persisted and sent off for background processing.&lt;/p&gt;
&lt;p&gt;Now, imagine that the background process needs to run a complex algorithm that would benefit from having access to a GPU. For that kind of system, you need infrastructure flexibility.&lt;/p&gt;
&lt;p&gt;Your application &lt;strong&gt;needs&lt;/strong&gt; a specific piece of infrastructure to function, so you need to take on the additional operational responsibility of running that infrastructure.&lt;/p&gt;
&lt;p&gt;The web component, on the other hand, is just a simple web interface that receives requests and passes them on. It’s largely irrelevant how that component runs; you just want it to be reliable and available.&lt;/p&gt;
&lt;p&gt;Different components of the same system have different requirements. Let’s make this more tangible for a moment.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.jameseastham.co.uk/assets/blog/serverless-spectrum-services.png&quot; alt=&quot;a spectrum displaying displaying where different cloud services sit on a spectrum of operational overhead vs infrastructure flexibility&quot;&gt;&lt;/p&gt;
&lt;p&gt;That’s the range of compute options you have across the cloud providers. Of course, running your own machine in a data centre also sits off the far left of that spectrum as well.&lt;/p&gt;
&lt;p&gt;The web component of your application could sit anywhere. My argument would be to run that as far right as possible.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Your users don’t care about the compute it runs on, your users just want the app to work&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The component that requires specific compute, though, clearly needs to be further left. You need control over the infrastructure. How far left, of course, depends. Which brings us onto the second dimension of compute decisions: cost.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.jameseastham.co.uk/assets/blog/serverless-spectrum-ops.png&quot; alt=&quot;a spectrum displaying technology cost on the far right and human cost on the left&quot;&gt;&lt;/p&gt;
&lt;p&gt;This cost slide generated the conversation, and it was actually a last-minute addition to the talk.&lt;/p&gt;
&lt;p&gt;The keynote from the previous evening at RustLab was an interesting real-world use case. The speaker briefly mentioned their choice of compute. They were running their Rust application on Kubernetes, and the reasoning was, “Lambda, ECS are more expensive.” I’m paraphrasing there, of course.&lt;/p&gt;
&lt;p&gt;My issue with that is that it reduces the cost of a system to the dollar value that AWS invoices you at the end of the month. That’s oversimplifying it.&lt;/p&gt;
&lt;p&gt;There’s a reason serverless services have a higher line item cost: You’re paying someone, somewhere, to run your infrastructure. The cloud provider is your platform team.&lt;/p&gt;
&lt;p&gt;Running virtual machines and operating Kubernetes clusters have costs beyond the line item cost that a cloud provider charges. As Werner Vogels so perfectly described in &lt;a href=&quot;https://www.thefrugalarchitect.com/&quot;&gt;the frugal architect&lt;/a&gt; cost and sustainability are important considerations for building modern systems. I don’t know Werner personally, but I’m pretty sure he isn’t just referring to the line item cost on your AWS bill.&lt;/p&gt;
&lt;p&gt;That isn’t me shitting on Kubernetes; it has a place in the world. But the vast majority of systems don’t need Kubernetes.&lt;/p&gt;
&lt;p&gt;Back when I worked at AWS, there was an interesting heuristic that I heard internally. Which was&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Kubernetes is useful if your ability to scale infrastructure dynamically is a differentiator for you business&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Going back to the app you’re building, the algorithm component has specific infrastructure requirements, and that infrastructure needs to dynamically scale up and down based on load. It feels like a good fit for Kubernetes.&lt;/p&gt;
&lt;p&gt;Does that necessarily mean your entire organisation needs to adopt Kubernetes? I’m not so sure. Could the web component run somewhere with lower operational overhead? Something like Lambda? somewhere where you can deploy the app and not worry about it until you need to make a change to it. Definitely.&lt;/p&gt;
&lt;p&gt;The counterargument is that once you’ve put time and effort into building a container platform, surely you might as well mandate that all teams use it.&lt;/p&gt;
&lt;p&gt;It’s a convincing argument. It’s a good argument. One I’m not sure I have a good argument against.&lt;/p&gt;
&lt;p&gt;My only critique of that approach is that it has introduced a single point of failure and a bottleneck into your system.&lt;/p&gt;
&lt;p&gt;The single point of failure is the cluster itself. You’re now running multiple (potentially critical systems) on top of a piece of infrastructure that relies on a single team (the platform team) patching and upgrading it every 6 months and in a way that ensures reliability.&lt;/p&gt;
&lt;p&gt;That’s entirely possible, of course. But it feels like we are returning to a world where Dev &amp;amp; Ops are split.&lt;/p&gt;
&lt;p&gt;One of the core principles of DevOps is “you build it, you run it.” Now, you build it, and someone else (a platform team) runs it. You might be on-call, and you might build observability and alerts. But fundamentally, someone else is running the underlying infrastructure.&lt;/p&gt;
&lt;p&gt;This brings me back to the idea of a compute spectrum. In my opinion, a good architect provides guardrails, not mandates.&lt;/p&gt;
&lt;p&gt;A guardrail could be your service has to communicate over well-defined APIs.&lt;/p&gt;
&lt;p&gt;A guardrail could be that your applications must be packaged as containers and be stateless.&lt;/p&gt;
&lt;p&gt;Empower teams to make decisions that suit the specifics of their workloads. Because, at the end of the day, those teams know their workloads the best.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Are you event based or event driven?</title><link>https://blog.jameseastham.co.uk/blog/event-based-or-event-driven-copy/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/event-based-or-event-driven-copy/</guid><description>Are you event based or event driven?</description><pubDate>Tue, 06 Feb 2024 21:12:03 GMT</pubDate><content:encoded>&lt;p&gt;You might think the title of this post is purely semantic? Surely if you are using events to trigger functionality, it doesn’t matter so much. James, you’re spending your time writing about something that doesn’t matter.&lt;/p&gt;
&lt;p&gt;Until it does.&lt;/p&gt;
&lt;p&gt;In his bestselling 2014 book Homosapiens, Yuval Hoah Harari discusses a history of humankind. And one of the key takeaways from that book is the importance of stories. Stories, and our use of words, are what set us apart as a species. Our ability to collaborate at scale, behind a single idea is what makes us different to the animals. Wether that be religion, nationality or the company you work for. These are all human constructs, detailed using language.&lt;/p&gt;
&lt;p&gt;Homo sapiens rules the world because it is the only animal that can believe in things that exist purely in its own imagination, such as gods, states, money, and human rights.&lt;/p&gt;
&lt;p&gt;Yes, animals work together. But it’s a far more primitive, survivalist kind of collaboration.&lt;/p&gt;
&lt;p&gt;So if languages and words are fundamental to human success. And software development is (at least for now, hello GenAI) a human endeavour. The language and words we use in our software is vitally important.&lt;/p&gt;
&lt;p&gt;And this is why this distinction is important.&lt;/p&gt;
&lt;p&gt;What Is Event Driven Architecture?
Event Driven Architecture, in my opinion, is a way of modelling the integration between your systems. And you model this integration using business events. And by business events, I mean things that are meaningful to your business.&lt;/p&gt;
&lt;p&gt;Event Driven Architecture allows the language of your business to drive it’s technical implementation - James Eastham&lt;/p&gt;
&lt;p&gt;You could look at two businesses in the same domain both building event-driven software. And the set of events in each system could be completely different.&lt;/p&gt;
&lt;p&gt;There will be similarities, in function and conceptual ideas, but the language that each of the businesses use will be different. Meaning the events driving the functionality will also be different.&lt;/p&gt;
&lt;p&gt;What Is Event Based Software?
Triggering functionality via events is not a new thing in software. I started out writing software in Windows Forms. For all you non .NET developers out there, Windows Forms is an old way of building desktop applications for Windows.&lt;/p&gt;
&lt;p&gt;Functionality in Windows Forms is driven by events. But these aren’t events that are unique to your business. They are things like ButtonClicked, MouseHovered or WindowResized.&lt;/p&gt;
&lt;p&gt;You could look at two systems in the same domain and if they were event based they would have the same set of events. ButtonClicked, MouseHovered so on and so forth.&lt;/p&gt;
&lt;p&gt;To bring this into modern, cloud based systems you could look at an S3ObjectCreated in the same way. This is a technical event, that notifies you of a technical thing that has happened. But how many non-technical people in your business would understand what that means?&lt;/p&gt;
&lt;p&gt;Who Cares?
This might still lead you to ask the question, who cares? If systems are triggering functionality with events, why do the semantics matter.&lt;/p&gt;
&lt;p&gt;From a technical perspective, you’d be correct. Both things are immutable facts, notifications of things that have happened somewhere else in the system.&lt;/p&gt;
&lt;p&gt;But how many of you have sat in a room with a non-technical person, talking about microservices, REST API’s and SQL databases and had the other persons eyes glaze over? Maybe they mutter under their breaths about ’these nerds talking techie all the time’ and nobody can agree about exactly what the system should do.&lt;/p&gt;
&lt;p&gt;Yeah, this is why you should care.&lt;/p&gt;
&lt;p&gt;S3ObjectCreated gives you the same problem. This is not the language of your business. InvoiceFileUploaded… now you’re talking.&lt;/p&gt;
&lt;p&gt;One of the key takeaways from running an event storming session is to agree on a shared language across your entire business. From technical to non-technical. Don’t waste all that effort by then using different, technical words in your system.&lt;/p&gt;
&lt;p&gt;In the same way Domain Driven Design gave us a shared language to talk about our architecture. Event Driven Architecture gives you a shared language to talk about communication. And in my opinion, that’s the real benefit of event driven systems.&lt;/p&gt;
&lt;p&gt;The takeaway from this, albeit short rambling stream of consciousness, is to be careful when you talk about being event driven. At it’s core, event driven architecture is about communication. Wether that be technical communication between two services, or the human communication between two people.&lt;/p&gt;
&lt;p&gt;Event Driven Architecture allows the language of your business to drive it’s technical implementation - James Eastham&lt;/p&gt;
&lt;p&gt;This is the first of a shorter selection of memos I’ll be publishing over the next few weeks. Gathering together my thinking around event driven architecture.&lt;/p&gt;
&lt;p&gt;I find writing a key part of developing my own thoughts, so if things get a little messy. I apologies in advance ;)&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Hexagonal Architecture with Rust &amp; AWS Lambda</title><link>https://blog.jameseastham.co.uk/blog/hexagonal-architecture-with-rust-aws-lambda/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/hexagonal-architecture-with-rust-aws-lambda/</guid><description>Hexagonal Architecture with Rust &amp; AWS Lambda</description><pubDate>Thu, 07 Dec 2023 21:12:03 GMT</pubDate><content:encoded>&lt;p&gt;I’ve spent a good portion of 2023 learning the basic principles of Rust. Fascinated by it’s performance, especially within the context of serverless systems. I dove deep, putting my object oriented, 10 years of .NET development to the side and attempted to learn Rust. And it’s been quite the journey.&lt;/p&gt;
&lt;p&gt;Early in my career, Domain Driven Design changed everything for me. Up until that point, I was more of a script kiddy than a software development. I look at times in my life as before the big blue book, and after. It sounds hyperbolic, but reading that book changed the trajectory of my career.&lt;/p&gt;
&lt;p&gt;Of course, domain driven design is something you apply at the design phase of your system. And once you’ve identified the core domain, you focus all of your efforts into building software in this area. As you move into the development phase, one of the best techniques I’ve found for actually writing code is clean architecture.&lt;/p&gt;
&lt;p&gt;Clean architecture, very similar to hexagonal architecture, ports and adapters and onion architecture is a way of structuring your code to separate the business logic from the code that deals with ‘infrastructure’ concerns.&lt;/p&gt;
&lt;p&gt;In a more traditional application context, this separates the outer layers of your application like API’s, databases and message buses from your actual business logic. Using AWS Lambda, this would separate the code that handles the Lamdba event from the actual business logic.&lt;/p&gt;
&lt;p&gt;I couldn’t quite get rid of all my .NET thinking, so I went ahead trying to bring this kind of programming model to Rust.&lt;/p&gt;
&lt;p&gt;In .NET, or other object oriented languages, you have things like encapsulation, inheritance, abstract classes and interfaces. You might define an interface as an IToDoRepository and then implement that interface with a DynamoDbTodoRepository that contains the logic specific to interface with DynamoDB.&lt;/p&gt;
&lt;p&gt;Let’s start at the more fundamental level. One of my favourite ideas from clean architecture is hiding certain pieces of functionality inside the domain. Let’s take the example of a ToDo application.&lt;/p&gt;
&lt;p&gt;A ToDo is quite a simple thing:&lt;/p&gt;
&lt;p&gt;/// Represents the structure of an incomplete ToDo #[non_exhaustive] #[derive(Deserialize, Serialize)]
pub struct ToDoItem {
pub id: String,
pub title: String,
pub is_complete: bool,
pub completed_on: String,
}
It has a title and if it has been completed or not. But actually, there might be quite a lot of business logic that goes into the management of a ToDo record. Off the top of my head, things like:&lt;/p&gt;
&lt;p&gt;A title cant be changed once a ToDo is completed
A ToDo can’t be ‘uncompleted’
The business logic for these 2 things, are related to the ToDo itself and therefore the ToDo should own the logic. There should be no way to update a title, or the completion status without calling a function on the ToDo itself.&lt;/p&gt;
&lt;p&gt;#[non_exhaustive]
pub enum ToDo {
/// Represents an incomplete ToDo item
Incomplete(IncompleteToDo),
/// Represents a complete ToDo item
Complete(CompleteToDo),
}&lt;/p&gt;
&lt;p&gt;impl ToDo {
/// Update the title of the existing ToDo.
/// If the ToDo is already completed then the title cannot be updated.
/// Returns a new ToDo
pub(crate) fn update_title(self, new_title: String) -&amp;gt; Result&amp;lt;ToDo, ValidationError&amp;gt; {
let new_title_value = Title::new(new_title);&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if new_title_value.is_err() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        return Err(new_title_value.err().unwrap());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let response = match &amp;amp;self {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ToDo::Incomplete(incomplete) =&amp;gt; ToDo::Incomplete(IncompleteToDo {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            to_do_id: incomplete.to_do_id.clone(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            title: new_title_value.unwrap(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            owner: OwnerId::new(incomplete.owner.to_string()).unwrap(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ToDo::Complete(complete) =&amp;gt; ToDo::Complete(CompleteToDo {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            to_do_id: complete.to_do_id.clone(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            title: Title::new(complete.title.to_string()).unwrap(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            owner: OwnerId::new(complete.owner.to_string()).unwrap(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            completed_on: complete.completed_on,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    Ok(response)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/// Set the ToDo as completed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;pub(crate) fn set_completed(self) -&amp;gt; ToDo {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    match &amp;amp;self {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ToDo::Incomplete(incomplete) =&amp;gt; ToDo::Complete(CompleteToDo {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            to_do_id: incomplete.to_do_id.clone(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            title: Title::new(incomplete.title.to_string()).unwrap(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            owner: OwnerId::new(incomplete.owner.to_string()).unwrap(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            completed_on: DateTime::parse_from_rfc3339(&amp;amp;Utc::now().to_rfc3339()).unwrap(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ToDo::Complete(complete) =&amp;gt; ToDo::Complete(CompleteToDo {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            to_do_id: complete.to_do_id.clone(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            title: Title::new(complete.title.to_string()).unwrap(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            owner: OwnerId::new(complete.owner.to_string()).unwrap(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            completed_on: complete.completed_on,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
Now, if any part of the application wants to update the title or the status they must use these two methods. The logic is encapsulated, and not spread all over your application.&lt;/p&gt;
&lt;p&gt;Enums are one of the features I love most about Rust. You can add implementations to an Enum, and then one of the options of the Enum can have a struct. The implemented methods on the enum can then do different things based on the enum options.&lt;/p&gt;
&lt;p&gt;As far as your application is concerned, you’re just calling methods on a ToDo. Inside your domain, the underlying logic differs depending on the type of ToDo you’re using.&lt;/p&gt;
&lt;p&gt;Another interesting idea of clean architecture, is separating infrastructure from application code. In .NET, that is typically done using interfaces and the implementation of them interfaces.&lt;/p&gt;
&lt;p&gt;Rust doesn’t have that luxury, interfaces aren’t a thing. However, you do have traits. Traits allow you to implement similar functionality to interfaces in Rust.&lt;/p&gt;
&lt;p&gt;#[async_trait]
pub trait ToDoRepo
{
async fn list(&amp;amp;self, user_id: &amp;amp;str) -&amp;gt; Result&amp;lt;Vec&lt;ToDo&gt;, RepositoryError&amp;gt;;&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;async fn create(&amp;amp;self, to_do: &amp;amp;ToDo) -&amp;gt; Result&amp;lt;(), RepositoryError&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;async fn get (&amp;amp;self, user_id: &amp;amp;str, todo_id: &amp;amp;str) -&amp;gt; Result&amp;lt;ToDo, RepositoryError&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
This is an implementation of a ToDoRepo, for interacting with a persistence layer. This could equally be a MessageBus.&lt;/p&gt;
&lt;p&gt;Code in your actual application then only makes method calls on the ToDoRepo trait, notice the use of the dyn keyword. The implementation of a ToDoRepo is passed in at runtime.&lt;/p&gt;
&lt;p&gt;pub async fn list_todos(owner: &amp;amp;String, client: &amp;amp;Arc&amp;lt;dyn ToDoRepo + Send + Sync&amp;gt;) -&amp;gt; Result&amp;lt;Vec&lt;ToDoItem&gt;, ()&amp;gt; {
let query_res = client.list(owner).await;&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;match query_res {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    Ok(todos) =&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        let mut to_do_items: Vec&amp;lt;ToDoItem&amp;gt; = Vec::new();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        for todo in todos {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            to_do_items.push(todo.into_dto());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        Ok(to_do_items)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    Err(_) =&amp;gt; Err(()),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
At the outermost layer of your application, in this case an Axum web APIm, the implementation of the ToDoRepo is defined and passed into your application state. Notice the use of a DynamoDbToDoRepo, that uses a DynamoDbClient from the newly GA AWS SDK for Rust.&lt;/p&gt;
&lt;p&gt;let shared_state = Arc::new(AppState {
todo_repo: Arc::new(DynamoDbToDoRepo::new(
dynamodb_client.clone(),
table_name.clone(),
)),
});&lt;/p&gt;
&lt;p&gt;let app = app(shared_state);&lt;/p&gt;
&lt;p&gt;let listener = tokio::net::TcpListener::bind(“127.0.0.1:8080”)
.await
.unwrap();&lt;/p&gt;
&lt;p&gt;axum::serve(listener, app).await.unwrap();
Early days in my exploration of the Rust language, but it’s been an interesting journey trying to marry together the two different programming models I hold in my head. The design principles of .NET, with the syntax and idioms of Rust.&lt;/p&gt;
&lt;p&gt;If you’re interested in the code from this article, check out the GitHub repo.&lt;/p&gt;
&lt;p&gt;For anyone reading this who is a more experience Rust developer, I’d love to hear if this is the right thing to do or if I’m heading down a long and lonely road.&lt;/p&gt;
&lt;p&gt;Until next time, James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Applications, Microservice Mistakes and Getting Things Done</title><link>https://blog.jameseastham.co.uk/blog/006-applications/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/006-applications/</guid><description>006 Applications, Microservice Mistakes and Getting Things Done</description><pubDate>Thu, 05 Oct 2023 21:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Don’t miss another newsletter by subscribing below :)&lt;/p&gt;
&lt;p&gt;Application Architecture as Code
One my favourite people in the industry is back again with another featured article. Gregor Hohpe makes an excellent case in this post for how important automation is when you’re building modern systems.&lt;/p&gt;
&lt;p&gt;Cloud without automation is just another data center&lt;/p&gt;
&lt;p&gt;What I find incredibly interesting about this post, is how Gregor ties the architecture of a system into the actual code you write. I spoke about a similar topic at the recent AWS Community Summit.&lt;/p&gt;
&lt;p&gt;With modern. serverless systems, the line between ‘infrastructure’ and ‘application’ code becomes blurry. If you are pulling message from a queue and starting a business workflow, well that’s an application decision.&lt;/p&gt;
&lt;p&gt;So how can you define your application architecture using code? Using the power of cloud development kits. These wonderful IaC tools that allow you to define cloud resources using programming languages of your choice.&lt;/p&gt;
&lt;p&gt;Now, you have the power to create abstractions that represent your architectural intent. And implement them using real programming languages.&lt;/p&gt;
&lt;p&gt;Brilliant! Check out Gregor’s article for a deep dive. One more quote from the article before you do though&lt;/p&gt;
&lt;p&gt;Document-oriented automation languages don’t represent data or control flow across application components well.&lt;/p&gt;
&lt;p&gt;Enjoy&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://architectelevator.com/cloud/iac-architecture-as-code/&quot;&gt;Read Here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Million Dollar Microservice Mistakes
I find this such an interesting view on microservices. From someone who was there in the trenches at the dawn of the buzzword.&lt;/p&gt;
&lt;p&gt;Microservices are great in the right hands. But the promise of ‘simplicity’ microservices bring is a misnomer.&lt;/p&gt;
&lt;p&gt;It might make your applications simpler, but the infrastructure and integrations to make things work certainly get more complex.&lt;/p&gt;
&lt;p&gt;In the land of the monolith, integration is as simple as a method call within the same process.&lt;/p&gt;
&lt;p&gt;In the land of microservices, this simple call needs to traverse a network. And networks are hard, just go Google the fallacies of distributed computing.&lt;/p&gt;
&lt;p&gt;They create separate “DevOps” squads or teams to manage Kubernetes clusters, centralized CI/CD pipelines, infrastructure, and automation. The outcome? Developers find themselves working in a ready-to-use yet restrictive environment, far from the promised autonomy of the microservices approach.&lt;/p&gt;
&lt;p&gt;Any article with a call-out to Conway’s Law is always worth a read.&lt;/p&gt;
&lt;p&gt;So before you decide microservices is right for your next project, give this article a read.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://levelup.gitconnected.com/microservices-the-million-dollar-mistake-your-company-is-making-c50eb428f732&quot;&gt;Read Here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Getting Shit Done
A minimum viable architecture (MVA) is something I am a huge fan of. I’ve spoken with people who have been scarred by enterprise architecture teams, big upfront design and waterfall projects.&lt;/p&gt;
&lt;p&gt;Architecture doesn’t have to be that way.&lt;/p&gt;
&lt;p&gt;Architecture is an enabler, it allows you think deeply about a problem before you start building. But getting ‘just enough’ architecture is difficult.&lt;/p&gt;
&lt;p&gt;This article proposes a set of criteria you can use to define a definition of done (DoD) for your architectures. To ensure you consider the architectural characteristics that are important to you.&lt;/p&gt;
&lt;p&gt;So instead of spending weeks and months drawing diagrams and documenting decisions. You can align your architecture to the things that matter most to your business. Once you’ve addressed the things that matter, you have a minimum viable architecture.&lt;/p&gt;
&lt;p&gt;Once you have an MvA, you can move on and start building. Safe in the knowledge you’ve thought about all the key components of your system.&lt;/p&gt;
&lt;p&gt;The product evolves MVP by MVP. Each MVP should ideally increase customer satisfaction with the product, while each MVA should increase the system’s quality while supporting the MVP delivery&lt;/p&gt;
&lt;p&gt;This article also discusses why continuous deployment is vital for success. Honestly, if I was to build a brand new application now. The first thing I would build is my pipeline. Once you can ship changes quickly and safely, well the rest is easy……&lt;/p&gt;
&lt;p&gt;Don’t quote me on that.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.infoq.com/articles/definition-of-done-mva/&quot;&gt;Read Here&lt;/a&gt;&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Debugging Cleaning Testing</title><link>https://blog.jameseastham.co.uk/blog/debugging-cleaning-testing/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/debugging-cleaning-testing/</guid><description>Why architects should debug issues, &apos;cleaning&apos; up your architecture and testing event driven systems.</description><pubDate>Wed, 20 Sep 2023 16:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;debugging&quot;&gt;Debugging&lt;/h2&gt;
&lt;p&gt;For you architects reading this, you should get involved in debugging and production outages…&lt;/p&gt;
&lt;p&gt;I know, I know. Your ivory tower is super comfortable with the reclining chairs and central heating. But the insight you can gain from getting down into the engine room is priceless.&lt;/p&gt;
&lt;p&gt;One of the easiest ways to understand the constraints of a system is at the exact point these fringes are being pushed. Production outages and issues tell you that.&lt;/p&gt;
&lt;p&gt;In this article, Gregor shows that&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A fantastic way in which systems tell us that we are wrong is debugging (including trouble-shooting operational issues). Debugging happens when reality deviates from what you intended it to be, i.e., you were wrong in some way. The task now is to figure out where you were wrong. That means the happiest moment of debugging is when you find out where you were wrong:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Gregor Hohpe, Debugging Architects&lt;/p&gt;
&lt;p&gt;Debugging gives you priceless insight. Which you can take back up to ivory tower and use to improve that component of a system, but also the wider system.&lt;/p&gt;
&lt;p&gt;One of your jobs as a modern software architect is to think about the wider system, the architecture of it’s entirety and the interplay between the smaller components.&lt;/p&gt;
&lt;p&gt;Understanding where one component went wrong gives you a valuable lesson. You can take that lesson to other components to stop them making the same mistake.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://architectelevator.com/transformation/debugging-architect/&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;cleaning&quot;&gt;Cleaning&lt;/h2&gt;
&lt;p&gt;Don’t worry, this newsletter hasn’t magically transformed into good housekeeping.&lt;/p&gt;
&lt;p&gt;Let’s talk about clean architecture.&lt;/p&gt;
&lt;p&gt;I’ve seen various ‘hot takes’ and commentary on social media recently arguing that clean architecture is overkill.&lt;/p&gt;
&lt;p&gt;It adds a lot of unnecessary boilerplate and formality etc etc etc…&lt;/p&gt;
&lt;p&gt;This post from the Software Alchemy blog gives you an introduction and also shows how clean architecture fits into the wider ideas of domain driven design.&lt;/p&gt;
&lt;p&gt;The ‘hot takes’ are interesting though. And I think there is a middle ground to be found here.&lt;/p&gt;
&lt;p&gt;One thing I’ve learned over the years is that simple is good. So if you’re building a simple system (I’m looking at all the CRUD API’s out there), DDD and clean architecture are overkill. A simple repository pattern with some API endpoints will work perfectly.&lt;/p&gt;
&lt;p&gt;But, and it’s a big but. If you’re working on a core domain that is complex and evolves quickly, putting time into the structure of your code upfront will save you time in the long run.&lt;/p&gt;
&lt;p&gt;Initially, it may seem more complex. But as your system develops, the simplicity becomes clear.&lt;/p&gt;
&lt;p&gt;As everything in our industry comes back to, it ALWAYS depends. The best heuristic to use? Simple is good, so keep it simple. Adopt the complexity when the business and system requirements need it.&lt;/p&gt;
&lt;p&gt;It’s part of the reason I love AWS Lambda, simple.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.jacobsdata.com/2020/02/19/a-brief-intro-to-clean-architecture-clean-ddd-and-cqrs&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;testing&quot;&gt;Testing&lt;/h2&gt;
&lt;p&gt;Event Driven Architecture (EDA), one of the most common patterns in modern software development.&lt;/p&gt;
&lt;p&gt;So common, I’m going to be talking about it at NDC London 2024.&lt;/p&gt;
&lt;p&gt;The benefits of adopting EDA are SEEMINGLY infinite. Loose coupling, asynchronous communication, teams operating independently, extensibility built in.&lt;/p&gt;
&lt;p&gt;And then you need to test it…&lt;/p&gt;
&lt;p&gt;Testing event driven systems is hard. Mostly because of their asynchronous nature.&lt;/p&gt;
&lt;p&gt;If you’re testing a synchronous process, you Act, and then once the response comes back you Assert.&lt;/p&gt;
&lt;p&gt;With an event driven system, you Act and then have know way of knowing when is the right time to Assert. Of course, you can assert that your original request completes successfully. But how do you ensure that the asynchronous process you expect to run in the future actually happens?&lt;/p&gt;
&lt;p&gt;This article from Steve Morland tackles these testing challenges through a deep dive into how his company actually worked through this problem.&lt;/p&gt;
&lt;p&gt;It’s AWS specific, but the process used could be applied anywhere.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/@smorland/testing-event-driven-applications-using-eventbridge-a-four-year-journey-8ed0c80fc4ca&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Learning Software Architecture; Start With Why!</title><link>https://blog.jameseastham.co.uk/blog/architecture-start-with-why/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/architecture-start-with-why/</guid><description>Many courses in software architecture and software in general focus on specific languages, technologies and services. This is great in the short term, but does not build the fundamental skills required to move in an industry as fast-paced as software. When learning a new technical domain, always start with why, move to the how before finally diving into the what. These foundational skills, coupled with a growth mindset, set up a long term career in technology.</description><pubDate>Wed, 13 Sep 2023 14:00:00 GMT</pubDate><content:encoded>&lt;p&gt;61,698,933!&lt;/p&gt;
&lt;p&gt;That’s the number of views (at the time of writing) &lt;a href=&quot;https://www.ted.com/talks/simon_sinek_how_great_leaders_inspire_action/no-comments&quot;&gt;Simon Sinek’s TED talk on ‘How great leaders inspire action’&lt;/a&gt; has. A fundamental idea from the talk is the idea of a golden circle, and how we default to approaching things in the complete opposite way.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.jameseastham.co.uk/assets/golden-circle.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Many of us approach things with an outside in approach. We start with what, take steps to work out how, and rarely worry too much about the why. This is a flawed approach. Starting with why, at least in business, explains your purpose and why you are doing the thing you are doing. People buy your why, not your what. Yet many businesses start with the what, and completely lose the sense of purpose. Your why drives the relationship with your customers.&lt;/p&gt;
&lt;p&gt;You might wonder how this short piece of business advice relates to how we teach software. But let’s take this same golden circle, and apply it to how many of us try to learn about software architecture.&lt;/p&gt;
&lt;p&gt;People interested in software architecture often ask me which AWS service to learn first. Or which certification to take. Do I learn about serverless or containers? Event driven architecture or microservices? These areas are inevitably ones you will need to learn about at some point, but they are &lt;strong&gt;unlikely&lt;/strong&gt; to be the best the place to start.&lt;/p&gt;
&lt;p&gt;You are starting with &lt;strong&gt;what&lt;/strong&gt;! Instead, start with &lt;strong&gt;why&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;starting-with-why&quot;&gt;Starting with Why&lt;/h2&gt;
&lt;p&gt;Build your knowledge from &lt;a href=&quot;https://fs.blog/first-principles/&quot;&gt;first principles&lt;/a&gt;. Technology iterates on itself quickly, and every iteration takes a problem seen previously and makes it better. These iterations stack on top of each other to give us the technology choices we have today.&lt;/p&gt;
&lt;p&gt;On-Premise servers -&amp;gt; Elastic Cloud Servers -&amp;gt; Containers -&amp;gt; Container Orchestrators -&amp;gt; Serverless&lt;/p&gt;
&lt;p&gt;The most famous saying in software architecture is &lt;strong&gt;it depends&lt;/strong&gt;. Taking a specific technology driven approach, to learning software architecture limits your ‘it depends’ to the specific niche of technology you are learning. If you have a hammer, everything looks like a nail. If you have a &lt;a href=&quot;https://aws.amazon.com/lambda/&quot;&gt;Lambda&lt;/a&gt; function, everything looks like it’s event driven.&lt;/p&gt;
&lt;p&gt;Instead of asking why exactly are we trying to hang this thing from the wall?&lt;/p&gt;
&lt;p&gt;Let’s take databases as an example. &lt;a href=&quot;https://aws.amazon.com/dynamodb/&quot;&gt;DynamoDB&lt;/a&gt; is a popular, fast and flexible NoSQL database service provided by AWS. It’s actually my second favourite AWS service (just beaten by &lt;a href=&quot;https://aws.amazon.com/step-functions/&quot;&gt;Step Functions&lt;/a&gt; if you’re interested). DynamoDB is largely schemaless. The schema of the items you write is determined at runtime.&lt;/p&gt;
&lt;p&gt;What this means is that you can store almost anything in DynamoDB, in any format. It’s an incredibly flexible database that could probably fit almost any application use case.&lt;/p&gt;
&lt;p&gt;That flexibility is one of DynamoDB’s biggest strengths, and also it’s greatest downfall if misused. If you spend all of your time learning about the specific API’s of DynamoDB, you understand single-table design, global secondary indexes, sparse indexes, read and write capacity units but never understand the why… Well then there is every possibility you may choose to use DynamoDB in a scenario where it doesn’t actually fit.&lt;/p&gt;
&lt;p&gt;Traditional relational databases still have a perfectly valid use case in modern technology. As do graph and time series databases. There is a reason AWS (currently) has &lt;a href=&quot;https://aws.amazon.com/products/databases/&quot;&gt;15 different database services&lt;/a&gt;. Yet if you are stuck in your little DynamoDB bubble you never even look up to see what else is out there.&lt;/p&gt;
&lt;p&gt;I’m not suggesting everyone needs to go deep on every single different type of database, but understanding the history of why we got to where we are is important. &lt;a href=&quot;https://www.amazon.co.uk/Designing-Data-Intensive-Applications-Reliable-Maintainable/dp/1449373321&quot;&gt;Designing Data-Intensive Applications by Martin Klepmann&lt;/a&gt; is an absolute goldmine for this content. Even reading the first 3 chapters of what is an admittedly dense technical book, would give you a &lt;strong&gt;huge&lt;/strong&gt; architectural advantage because you understand enough to make an informed decision.&lt;/p&gt;
&lt;h2 id=&quot;a-generalist-growth-mindset&quot;&gt;A Generalist Growth Mindset&lt;/h2&gt;
&lt;p&gt;In the excellent book &lt;a href=&quot;https://www.amazon.co.uk/Range-Key-Success-Performance-Education/dp/1509843523&quot;&gt;Range&lt;/a&gt; David Epstein discusses how being a generalist is a fantastic skill to have. The cross-pollination of different ideas, from different domains, leads to better decision making and more creative thinking.&lt;/p&gt;
&lt;p&gt;Having a general idea of the use cases for the different database options, a set of first principles that guide your decision making, forces you to start from the problem you are solving and work outwards to &lt;strong&gt;what&lt;/strong&gt; database you are going to use. Suddenly, the decision between 16 different AWS database services becomes less challenging. You’re making your decision based on the specific problem domain, applying your general knowledge of all databases to work out to the best technology choice.&lt;/p&gt;
&lt;p&gt;Once you’ve gone through the why and reached the what, it’s time to double down on a growth mindset. &lt;a href=&quot;https://www.ted.com/speakers/carol_dweck&quot;&gt;Professor Carol Dweck&lt;/a&gt; proposed the idea of fixed and growth mindsets. A person holding a fixed mindset assumes that their abilities are immutable, whereas a person with a growth mindset acknowledges that they can acquire and develop any new skill with sufficient time and effort.&lt;/p&gt;
&lt;p&gt;Fixed = I don’t know
Growth = I don’t know, &lt;strong&gt;yet&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Baseline your thinking as a generalist and start from first principles, before doubling down on your growth mindset to pickup a new technology as and when the time arises.&lt;/p&gt;
&lt;p&gt;Starting from why; a skill all architects, aspiring or otherwise, should cultivate at all times.&lt;/p&gt;
&lt;p&gt;As always, thanks for reading.
James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Thinking Changing Scaling</title><link>https://blog.jameseastham.co.uk/blog/thinking-changing-scaling/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/thinking-changing-scaling/</guid><description>Thinking; something you spend an awful lot of time doing. Whether that be about what you’re working on now, something new you need to build in the future or a particularly gnarly issue, you can’t get your head round. So surely, having a set of tools you can use to aid your thinking is useful? Right? One of my favourite frameworks for thinking about problems is using First Principles.</description><pubDate>Wed, 13 Sep 2023 14:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;thinking&quot;&gt;Thinking&lt;/h2&gt;
&lt;p&gt;Thinking; something you spend an awful lot of time doing. Whether that be about what you’re working on now, something new you need to build in the future or a particularly gnarly issue, you can’t get your head round.&lt;/p&gt;
&lt;p&gt;So surely, having a set of tools you can use to aid your thinking is useful? Right?&lt;/p&gt;
&lt;p&gt;One of my favourite frameworks for thinking about problems is using First Principles.&lt;/p&gt;
&lt;p&gt;First Principles thinking boils a problem down to its purest form, the smallest potential building blocks. And uses them building blocks to build up a solution.&lt;/p&gt;
&lt;p&gt;Imaging you are building something on AWS. For argument’s sake, you’re deploying an application to a virtual machine. You’re trying and trying but your application won’t scale.&lt;/p&gt;
&lt;p&gt;You’ve re-written modules, optimised hot paths, you’ve done everything you possibly could.&lt;/p&gt;
&lt;p&gt;First principles thinking boils it down to its core. Forget about your application code, the specific language or technology choice. What you need is a software system that scales to meet X demand. That’s the root of the challenge you’re solving.&lt;/p&gt;
&lt;p&gt;Now that you know that, you can build back up. “If I was building a system that scales, I will do X”. Now you have a solution to work towards.&lt;/p&gt;
&lt;p&gt;This article from the Farnham Street blog is not technology specific. But will walk you through the process of thinking from first principles.&lt;/p&gt;
&lt;p&gt;Top tip, it works much better if you do things the old-fashioned way with a pen and notepad.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://fs.blog/first-principles/&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;changing&quot;&gt;Changing&lt;/h2&gt;
&lt;p&gt;Change, the one and only constant in life.&lt;/p&gt;
&lt;p&gt;The only thing you can guarantee at any point in the future is that something will have changed.&lt;/p&gt;
&lt;p&gt;The business requirements of your system.&lt;/p&gt;
&lt;p&gt;The features of a service you’re using.&lt;/p&gt;
&lt;p&gt;The structure of your organisation.&lt;/p&gt;
&lt;p&gt;Your life situation.&lt;/p&gt;
&lt;p&gt;Change is the only constant. So effectively managing change is a pretty fundamental life skill.&lt;/p&gt;
&lt;p&gt;Something you will do in your career in software is bringing about change. Sometimes, you’re the person causing the change and requisite stress for the rest of your organisation.&lt;/p&gt;
&lt;p&gt;When you find yourself in that situation, how can you do it effectively? Minimising the feelings of upheaval and stress for the people your change is affecting.&lt;/p&gt;
&lt;p&gt;In this article, Mary Lynn Manns (author of the book Fearless Change) proposes that you can use emotional connection to help with the change process.&lt;/p&gt;
&lt;p&gt;If you connect with people on a deeper level and recognise how they are feeling, the change process will be a lot smoother. I promise 🙂&lt;/p&gt;
&lt;p&gt;For some super practical tips, go read the article.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.infoq.com/articles/emotional-connection-drive-change&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;scaling&quot;&gt;Scaling&lt;/h2&gt;
&lt;p&gt;You are working within a certain set of scaling constraints. Whether you’re Netflix servicing millions of users, or a smaller organisation just meeting the needs of your first 100 customers.&lt;/p&gt;
&lt;p&gt;Banging your head against the proverbial scaling wall is something you’ll inevitably do in your career.&lt;/p&gt;
&lt;p&gt;And obviously, you’ll only realise your system can’t scale once everything is on fire.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.jameseastham.co.uk/assets/this-is-fine.gif&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A lesser talked about scaling issue, though, is one of architecture. How do you scale the practice of architecture across your entire organisation?&lt;/p&gt;
&lt;p&gt;At one end of the spectrum, you have the centralised enterprise architecture team. Done badly, this leads to a team of architects sat in their ivory tower dictating decisions on the rest of the organisation.&lt;/p&gt;
&lt;p&gt;At the other end, you shift the responsibility to the individual development teams. Let teams architect their own solutions. Which sounds magical, but then what happens when you have an architectural requirement that affects multiple teams or even the entire organisation?&lt;/p&gt;
&lt;p&gt;Scaling architecture is difficult.&lt;/p&gt;
&lt;p&gt;Thankfully, Andrew Harmel-Law has some suggestions for you. What’s even better, is that Andrew’s proposed process is so simple, I almost fell off my chair in surprise.&lt;/p&gt;
&lt;p&gt;Word of warning, this one is a long read. To tempt you in, I’m going to pull a quote from the opening section:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’ll explain how, within this alternative approach, everyone can do the architecting they need, safely and efficiently, without everything descending into chaos.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Andrew Harmel-Law&lt;/p&gt;
&lt;p&gt;Sounds perfect! So grab a cup of your favourite hot or cold beverage and settle in for the read.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://martinfowler.com/articles/scaling-architecture-conversationally.html&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Elevators, Modules &amp; Microservices</title><link>https://blog.jameseastham.co.uk/blog/elevators-modules-microservics/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/elevators-modules-microservics/</guid><description>My weekly newsletter from 2023-09-06. In this weeks issue, you will learn about how to ride the architects elevator, the importance of modularizing your software and what Netflix learnt from building microservices.</description><pubDate>Sat, 09 Sep 2023 16:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-software-architects-elevator&quot;&gt;The Software Architects Elevator&lt;/h2&gt;
&lt;p&gt;If you’ve been around the software industry for a period of time you’ll inevitably have come across Gregor Hohpe. If not, have you been living under a rock?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.jameseastham.co.uk/assets/rock.gif&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Anyway, amongst the many incredible books Gregor has written (including one of my favourite software books of all time Enterprise Integration Patterns), one of the most impactful on my career is the Architects Elevator. The idea of the architects elevator is that to be a successful architect you need to spend time both in the boardroom, and down in the engine room with development teams.&lt;/p&gt;
&lt;p&gt;In this talk, Gregor covers the core ideas of the architects elevator and why it is so important.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Zq2VcRZmz78&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;modular-monoliths&quot;&gt;Modular Monoliths&lt;/h2&gt;
&lt;p&gt;The monolith gets a bad rap, and can be an incredibly useful tool in your toolbox when build correctly. There, I said it! Please reach out on Twitter if you wish to continue this debate in a healthy, rational manner 😀&lt;/p&gt;
&lt;p&gt;One of the ways to ensure your monolithic application is successful is to make it modular. Logical separations in your application aren’t just for microservices you know. The modular monolith is one of my favourite patterns for building net new applications.&lt;/p&gt;
&lt;p&gt;There are a number of benefits of doing this, and I won’t cover them all here. Instead, I’ll let the wonderful Milan Jovanovic talk you through. It this article, Milan discusses the communication patterns in a modular monolith covering both synchronous and asynchronous communication.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.milanjovanovic.tech/blog/modular-monolith-communication-patterns&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;some-love-for-microservices&quot;&gt;Some Love For Microservices&lt;/h2&gt;
&lt;p&gt;To continue with the system design theme, it would be remiss of me to not include some content on the buzzword of the decade… The microservice.&lt;/p&gt;
&lt;p&gt;This presentation by Adrian Cockcroft discusses the lessons learned from building microservices at Netflix. One of the most interesting things I took from this talk is that Adrian didn’t just talk about technical. On opening, he discusses people and culture and how important they are in being successful with microservices.&lt;/p&gt;
&lt;p&gt;Which is something I’ve seen time and time again in the industry. The technical implementation of a microservices architecture is well documented. But if the culture of your organisation ain’t ready for microservices, then frankly you’re in for a world of pain.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.infoq.com/presentations/microservices-netflix-industry&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Art, Production and Domain Driven Design</title><link>https://blog.jameseastham.co.uk/blog/art-production-domain-driven-design/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/art-production-domain-driven-design/</guid><description>My weekly newsletter from 2023-09-06. In this weeks issue, you will learn about how art and the creative act applies to the software industry, building production grade software and how to use domain driven design in the real world.</description><pubDate>Wed, 06 Sep 2023 16:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;engineering-as-art&quot;&gt;Engineering as Art&lt;/h2&gt;
&lt;p&gt;Something many people don’t know about me is that I studied art right until I was 18. I was never technically brilliant, but what I had was creating thinking and plenty of ideas.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.jameseastham.co.uk/assets/art.gif&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Sometimes, I struggled to put them into practice. Which is much like my career in software as well.&lt;/p&gt;
&lt;p&gt;When you think about software engineering, art is not be the first thing that comes to mind. But actually, this article by David Grizzanti proposes we are artists.&lt;/p&gt;
&lt;p&gt;And much like David, I have finished reading Rick Rubin’s book ‘The Creative Act’&lt;/p&gt;
&lt;p&gt;And much like David, I was reading it thinking just how many parallels there are between creative work and our work in the software engineering world. Especially as you move to higher level roles.&lt;/p&gt;
&lt;p&gt;If you follow some practices that the more typical artist follows, you could be surprised at how that affects your day to day work.&lt;/p&gt;
&lt;p&gt;Adopting a beginner’s mind, being open to new ideas, getting outside your comfort zone or trying out new mediums (I’m looking at you Python). These things help cultivate a skill set that will set you apart.&lt;/p&gt;
&lt;p&gt;For an incredibly motivating look at our industry, check out the article below.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.infoq.com/articles/engineering-art-embracing-creativity/&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;building-production-grade-software&quot;&gt;Building Production Grade Software&lt;/h2&gt;
&lt;p&gt;Ah, the words ‘production ready’. Something I talk about all. Of. The. Time. It’s great to show a new technology or service using a simple hello world example. But where we fail as an industry is moving beyond that.&lt;/p&gt;
&lt;p&gt;Once I have my hello world, how do I apply that to my big enterprise application with 10,000+ users?&lt;/p&gt;
&lt;p&gt;CICD, observability, performance tuning, resilience. There are many more things to think about than writing code.&lt;/p&gt;
&lt;p&gt;So when I came across this article from Allen Helton on, I was surprised to ask the same question. What actually is ‘production ready’ software?&lt;/p&gt;
&lt;p&gt;With an excellent analogy and tangible examples, Allen shows exactly what production grade actually means. As well as pointing out a few key architectural ‘-ilities’. And I agree with lots of his points.&lt;/p&gt;
&lt;p&gt;That’s not to say you will never write another POC. I just ask that you keep things like performance, maintainability, operability and resilience in the back of your mind as your building it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.readysetcloud.io/blog/allen.helton/what-is-production-grade-software/?trk=feed_main-feed-card_feed-article-content&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;doman-driven-design-in-the-real-world&quot;&gt;Doman Driven Design in the Real World&lt;/h2&gt;
&lt;p&gt;And to round out this issue, I wanted to share a post from one of my favourite new writers I’ve discovered in the last few weeks. A mentor recommended hila to me, so I had to dive straight in.&lt;/p&gt;
&lt;p&gt;In this article, Hila covers the practical aspects of Domain Driven Design. As a long-time advocate of DDD (the big blue book was the first software book I ever read) it’s great to see it applied in a real world setting.&lt;/p&gt;
&lt;p&gt;I LOVE, how the ways of working at Augury are wrapped in ‘when → then’ statements to explain exactly when to use certain concepts.&lt;/p&gt;
&lt;p&gt;I also LOVE, how the core ideas of DDD have been tweaked and changed to fit the specific needs of an organisation.&lt;/p&gt;
&lt;p&gt;DDD is a fantastic book, and a fantastic framework for thinking about software. But the ideas need to fit YOUR organisation. And these slight changes are a great example of how DDD can work for you.&lt;/p&gt;
&lt;p&gt;It also touched on one of my favourite topics, application integration. And patterns you can apply as you build cross-cutting services and shared interfaces you can use across your entire organisation.&lt;/p&gt;
&lt;p&gt;It even gives you an example of how to take an existing integration point, and refactor that into a different integration pattern.&lt;/p&gt;
&lt;p&gt;Brilliant stuff. Follow Hila once you fit the link below.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/augury-research-and-development/practical-ddd-aligning-generic-services-maturity-with-practical-patterns-43c0276d3875&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>The Essential Art of Sustainable Software Architecture</title><link>https://blog.jameseastham.co.uk/blog/the-essential-art-of-sustainable-architecture/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/the-essential-art-of-sustainable-architecture/</guid><description>Sustainability; a word we all hear an awful lot and one that means different things to different people. What does it  mean to be sustainable? The definition above sums it up for me, fulfil the needs of the present without compromising the future. Let&apos;s explore what makes up the art of sustainable software architecture, balanced across the environmental, economic and social pillars?</description><pubDate>Thu, 27 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;Sustainability consists of &lt;strong&gt;fulfilling&lt;/strong&gt; the &lt;strong&gt;needs&lt;/strong&gt; of &lt;strong&gt;current generations without compromising&lt;/strong&gt; the &lt;strong&gt;needs&lt;/strong&gt; of &lt;strong&gt;future generations&lt;/strong&gt;, while ensuring a balance between &lt;strong&gt;economic&lt;/strong&gt; growth, &lt;strong&gt;environmental&lt;/strong&gt; care and &lt;strong&gt;social&lt;/strong&gt; well-being.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sustainability; a word we hear an awful lot and one that means different things to different people. What does it mean to be sustainable? The definition above sums it up for me, fulfil the needs of the present without compromising the future.&lt;/p&gt;
&lt;p&gt;When we think about sustainability, our minds jump to climate change, making sure we re-use our shopping bags and making sure we recycle our plastic bottles. These are noble causes, as technologists, we have the &lt;strong&gt;potential&lt;/strong&gt; to make a &lt;strong&gt;bigger impact&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Software is taking over the world. Every single organisation on the planet is now considering itself a technology company.&lt;/p&gt;
&lt;p&gt;This gives us a huge opportunity to have a tremendous impact. Huge portions of the world are using software every single day. Is it not our responsibility to ensure that the software we architect meets the needs of the present, whilst optimising for the future?&lt;/p&gt;
&lt;p&gt;What makes up the art of sustainable software architecture, balanced across the environmental, economic and social pillars?&lt;/p&gt;
&lt;h2 id=&quot;environmental-software-architecture&quot;&gt;Environmental Software Architecture&lt;/h2&gt;
&lt;p&gt;The environmental pillar is imperative, and the most obvious when we think about sustainability. To create a more sustainable planet, and aim to mitigate climate change. There is a single word that springs to mind when I think about the environmental impact of our architectures:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Efficiency&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The ability to do more with as few resources as possible. The art of having the right resource, in the right place, at just the right time. With some of the recent innovations in software development, efficiency is a practical thing to implement.&lt;/p&gt;
&lt;h3 id=&quot;leveraging-the-cloud-for-efficiency&quot;&gt;Leveraging the cloud for efficiency&lt;/h3&gt;
&lt;p&gt;A report by &lt;a href=&quot;https://www.spglobal.com/marketintelligence/en/news-insights/research/carbon-reduction-in-cloud&quot;&gt;S&amp;amp;P Global Market Intelligence&lt;/a&gt; discusses the impact of moving workloads to the cloud.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Simply moving to using green energy is not going to deliver the desired — or the best — carbon reduction. The best place to go from a carbon reduction perspective is the cloud.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The report estimates that a combination of more up-to-date equipment and a better utilised fleet of hardware amounted to an 85% saving in energy usage. This is before considering the fact that many &lt;a href=&quot;https://sustainability.aboutamazon.co.uk/environment/the-cloud?energyType=true&quot;&gt;cloud providers are moving their data centres to use 100% renewable energy&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;architect-for-efficiency&quot;&gt;Architect for Efficiency&lt;/h3&gt;
&lt;p&gt;Many of you have heard of the cloud, and are likely already running some kind of workload in the cloud. But once in the cloud, how can we architect for efficiency? Thankfully, the architecture patterns that are the most efficient also are the most optimal ways to build modern software.&lt;/p&gt;
&lt;p&gt;Serverless-first, event driven architectures are a prevalent architectural pattern when building cloud native systems. Remember, one principle we are looking to optimise our systems is to do more with less. A system that scales to zero when it’s not in use, and reacts to events as they happen… What could’ve more optimised than that?&lt;/p&gt;
&lt;p&gt;Let’s unpack the two terms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Serverless first: A mindset when building software that defaults to leveraging serverless compute options like AWS Lambda. Shifting the operational burden on to the cloud provider. This enables the cloud provider to be efficient with the underlying compute as they can shift workloads around to meet demand.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Event Driven Architecture: A pattern in which business events drive functionality, coupled with an asynchronous first approach. A system which reacts to events as they happen, and defaults to running things asynchronously, provides ample opportunity to optimise for sustainability.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, a serverless event driven architecture may not always be the most optimal or even the most practical. I’m looking at all you GPU compute heavy folks out there. That said, it’s still possible to architect for efficiency.&lt;/p&gt;
&lt;p&gt;Defaulting to a single type of compute everywhere in your system is an anti-pattern. Choose the &lt;strong&gt;right compute&lt;/strong&gt; for your &lt;strong&gt;use case&lt;/strong&gt; and optimise accordingly.&lt;/p&gt;
&lt;p&gt;If that means running big GPU intensive EC2 instances, then go for it, but consider how you could be more efficient with the compute that you have.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Think asynchronous&lt;/strong&gt; first, default to using managed services and take intentional step outs away from this pattern where required.&lt;/p&gt;
&lt;p&gt;### Code for Efficiency&lt;/p&gt;
&lt;p&gt;Code is a fundamental part of any software system. There is so much nuance in an individual business use case that hand written, custom code is inevitable. Many of us (me included) default to familiarity. Debating the merits of a language based on syntax, performance and legibility (I’m looking at you Python).&lt;/p&gt;
&lt;p&gt;Something I rarely hear mentioned in programming languages, is the environmental impact. A group of extremely smart people out of various universities in &lt;a href=&quot;https://greenlab.di.uminho.pt/wp-content/uploads/2017/10/sleFinal.pdf&quot;&gt;Portugal have ran this analysis for us&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The report linked above analyses 27 well-known software languages and monitors the performance using 10 different programming problems, expressed in each of the languages. An interesting observation from this paper is that:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Compiled languages tend to be, as expected, the fastest and most energy efficient ones. On average, compiled languages consumed 120J to execute the solutions, while for virtual machine and interpreted languages this value was 576J and 2365J, respectively. This tendency can also be observed for execution time, since compiled languages took 5103ms, virtual machine languages took 20623ms, and interpreted languages took 87614ms (on average).”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I find this even more interesting considering how prevalent interpreted languages like Python and NodeJS are in our modern software world.&lt;/p&gt;
&lt;p&gt;Unsurprisingly, the top 5 languages for both energy efficiency and execution time:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;C&lt;/li&gt;
&lt;li&gt;Rust&lt;/li&gt;
&lt;li&gt;C++&lt;/li&gt;
&lt;li&gt;Ada&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And the bottom 5 for energy:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Perl&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Ruby&lt;/li&gt;
&lt;li&gt;JRuby&lt;/li&gt;
&lt;li&gt;Lua&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And execution time:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lua&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Perl&lt;/li&gt;
&lt;li&gt;Ruby&lt;/li&gt;
&lt;li&gt;Typescript
&lt;em&gt;See, my looks at Python weren’t completely off the mark&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Quick side note, Rust has also ranked as the most beloved programming language in the Stack Overflow developer survey for 7 years running (as of the 2022 survey).&lt;/p&gt;
&lt;p&gt;Now I’m not suggesting you all go away to learn Rust (although it’s a lot of fun) and re-write your entire applications. We will see more on this when we move on to the &lt;strong&gt;social&lt;/strong&gt; pillar of sustainable architecture. But understand the efficiencies of each language is important.&lt;/p&gt;
&lt;p&gt;Maybe you don’t re-write your entire application, but you re-write the most commonly used pieces of functionality to use a more efficient language. Taking Rust as a specific example, combined with AWS serverless compute, this is also likely to save you money as well.&lt;/p&gt;
&lt;h2 id=&quot;the-social-pillar-of-software-architecture&quot;&gt;The Social Pillar of Software Architecture&lt;/h2&gt;
&lt;p&gt;When I first looked at the pillars of sustainability, the social one made me stop and think. There is the obvious social impact of software; building software to solve the world’s hardest problems. But can be dive a little deeper into that, what about the day to day social impacts of the people building the software?&lt;/p&gt;
&lt;p&gt;I’m sure many of us have worked on applications where the code was an unruly big ball of complicated mud. Equally, I’m sure some of of us have worked inside code bases that are a perfectly modularised thing of beauty.&lt;/p&gt;
&lt;p&gt;Not all of us can work on software that is ‘changing the world’, but we can all aim to build software that considers the needs of future generations.&lt;/p&gt;
&lt;h3 id=&quot;enjoyable-to-work-on&quot;&gt;Enjoyable to work on&lt;/h3&gt;
&lt;p&gt;One of the most important characteristics of social software is a code base that is enjoyable to work on. I want to go to work and have fun solving problems, instead of battling with complexity, un-necessary abstractions and hard to read code.&lt;/p&gt;
&lt;p&gt;The boy scout rule is an excellent mantra to use here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Always leave the code better than you found it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Simple, easy to remember and forces you to think about continuously improving code. Maybe this is as simple as re-naming a variable to be more expressive. Maybe it’s adding additional services and functions to make the code more intentional.&lt;/p&gt;
&lt;p&gt;A rule of thumb I try to follow (and often fail at) is to write code that reads like a story. If you’re using a compiled language, using long easy to read variable names is irrelevant because the compiler will compress them down.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;c#&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; counter&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; currentIterator&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; list&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;c#&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; currentProductIndex&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; maxProducts&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;currentProductIndex&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; currentProduct&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; allProducts&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;currentProductIndex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I know which I prefer.&lt;/p&gt;
&lt;h3 id=&quot;reduce-cognitive-load&quot;&gt;Reduce cognitive load&lt;/h3&gt;
&lt;p&gt;Cognitive load is devastating to a software developer. Our brains can only hold so much information in our head at a time. When working on tasks, it functions more like a stick of RAM than an SSD.&lt;/p&gt;
&lt;p&gt;Reducing the cognitive load of a system enables your fellow developers to make more informed decisions about functionality. If I can consume a library with a well defined API taht abstracts away a complex task, that reduces my cognitive load. Giving me more mental cycles to focus on the problem at hand.&lt;/p&gt;
&lt;p&gt;Defaulting to a modular design, whether that be a modular monolith or microservices, reduces this cognitive burden. Especially when coupled with domain driven design, defined bounded contexts and organising teams around features and not technical domains.&lt;/p&gt;
&lt;p&gt;If I’m a developer working on the product microservice, I can become fully embedded in the world of products within the organisation. I need to get some customer information, well the customer team has a well defined API interface with excellent documentation. They even produced an SDK for communication, excellent! Cognitive load removed.&lt;/p&gt;
&lt;h3 id=&quot;fast-feedback&quot;&gt;Fast Feedback&lt;/h3&gt;
&lt;p&gt;Dopamine; the neurochemical responsible for almost all of our modern addictions. That little burst of pleasure you get when you get a new notification… That’s dopamine in action. It’s not all bad though. We can leverage dopamine in positive ways as well.&lt;/p&gt;
&lt;p&gt;Fast feedback loops within the application, typically with a well defined set of test cases, help enable this reinforcement. Imagine working within a code base and continuously running the test cases seeing all of them green icons light up. You can feel that dopamine hit already, can’t you?&lt;/p&gt;
&lt;p&gt;These fast feedback loops also help enable mastery of the domain and language. A core component of mastering anything is quickly being able to course correct.&lt;/p&gt;
&lt;p&gt;Tests light up green = dopamine hit&lt;/p&gt;
&lt;p&gt;Tests go red = an opportunity to increase your mastery&lt;/p&gt;
&lt;h3 id=&quot;extensible--observable&quot;&gt;Extensible &amp;amp; Observable&lt;/h3&gt;
&lt;p&gt;The last topic I wanted to touch on around the social impact is that of extensibility and observability. I want to work within a system in which I can easily extend it to add new functionality, and observe/debug it when things go wrong.&lt;/p&gt;
&lt;p&gt;Some of the most frustrating times in my career have been through trying to debug a problem that has little to no logs or tracing.&lt;/p&gt;
&lt;p&gt;Building with extensibility and observability in mind will impact the needs of future developers, meeting our commitment to the social pillar.&lt;/p&gt;
&lt;p&gt;The extensibility angle ties nicely in with our serverless-first, event driven mindset. An event driven system is extensible. If your system behaviour is driven by a set of business events shared between bounded contexts through some kind of central event stream, hooking into that event stream to add new functionality becomes incredibly easy. Coupling that central event stream with a schema registry and you are in a fantastically extensible place.&lt;/p&gt;
&lt;p&gt;The observability angle applies to much more than the social component. Observability will help us environmentally and economically (you can’t measure what you can’t improve), as well as socially (understanding what the heck is going on in a system).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mindset of the sustainable architect is to be serverless-first, asynchronous and event driven by nature with observability as a fundamental tenant.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-economic-pillar-of-sustainable-architecture&quot;&gt;The Economic Pillar of Sustainable Architecture&lt;/h2&gt;
&lt;p&gt;If the social pillar made me pause for thought, this one had me stumped for a little whilse. The definition of the economic pillar is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This pillar is based on companies’ ability to contribute to economic development and growth.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As architects and engineers, we have little say in our organisations’ wider policies on contributing to economic development and growth. So what does economic development and growth mean within the context of software?&lt;/p&gt;
&lt;p&gt;Within this pillar, I see the practical patterns &amp;amp; steps you can take as an architect to contribute to the development and growth of your software system sustainably. There are many ties with the environmental pillar here, with &lt;strong&gt;efficiency&lt;/strong&gt; being a fundamental component. So let’s consider the economics of the different system components.&lt;/p&gt;
&lt;h3 id=&quot;compute&quot;&gt;Compute&lt;/h3&gt;
&lt;p&gt;We’ve discussed compute already, defaulting to a serverless-first mindset. But there are several additional patterns and practices to help enable sustainable use of compute.&lt;/p&gt;
&lt;p&gt;The first is to &lt;strong&gt;optimise for stateless&lt;/strong&gt; compute. Aim for your application layer to hold little to no state. It helps to enable the event driven, reactive compute we are looking for. If your application requires in-memory state, then you restrict the type of compute you can use, as well as how you and your cloud provider can shift that compute around.&lt;/p&gt;
&lt;p&gt;Holding an element of data in memory may be useful from a performance perspective, caching for example, but you should not rely on it.&lt;/p&gt;
&lt;p&gt;Second, and related to the earlier point, optimise the actual compute itself. This may mean using more optimised chipsets (x86 vs ARM). Or it may mean optimising the type of compute you have. If you’re within the serverless world, this may mean optimising the memory allocation of your function to get the optimal performance vs memory balance. If you’re in the physical server world, this may use the most optimal instance type (compute vs memory vs network optimised) for your specific use case.&lt;/p&gt;
&lt;p&gt;There is not a one size fits all in compute, it &lt;em&gt;always depends&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;networking--data-transfer&quot;&gt;Networking / Data Transfer&lt;/h3&gt;
&lt;p&gt;The environmental impact of networking and data transfer is difficult to quantify, as there are so many variables. That doesn’t mean we can’t be more economical though.&lt;/p&gt;
&lt;p&gt;Ask yourself the question, what is the minimal viable data I need to perform the task I have? The backend for front-end (BFF) pattern is excellent for this, alongside technologies like GraphQL. The aim here - ensure only useful data is transferred.&lt;/p&gt;
&lt;p&gt;Compression is another decision point that we will see again when we discuss storage. Many workloads, including almost every single one I have built, default to JSON as the data transfer medium. Understandably so. It’s human readable and relatively succinct. But actually, as we are passing data over the wire, can we not make this even more efficient?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://protobuf.dev&quot;&gt;Protobuf&lt;/a&gt; and &lt;a href=&quot;https://msgpack.org/index.html&quot;&gt;MessagePack&lt;/a&gt; are two such technologies specifically targeting efficient binary serialization, whilst still maintaining an element of schema and operability.&lt;/p&gt;
&lt;p&gt;Caching and data transfer distance are two concepts that go hand in hand. That is using content delivery networks (CDN) to get the data and compute as close to your users as possible. Caching data at the end, as well as running compute at the edge, reduces the network ‘cost’ of transferring the data.&lt;/p&gt;
&lt;p&gt;Caching is also valuable within our backend systems. If you are working within a micro-services architecture, it’s likely you have an element of communication across a network. Consider if you could cache external data within your own service to reduce the network transfer cost and secondarily reducing the compute load on your other systems (a big tick in the social pillar here as well).&lt;/p&gt;
&lt;p&gt;Micro-services architectures, coupled with event driven architecture, also bring up an important point of debate around event schema design. There is a probably a separate blog post within this topic, but determining what you include in your event is important. Events that are too sparse result in many calls back to the producer service to retrieve additional data. A ‘fat’ event results in a larger initial cost as it distributes the event to all the subscribers.&lt;/p&gt;
&lt;p&gt;That said, if we truly optimising for sustainability, my preference is for a fat event with a combination of JSON &amp;amp; Binary. We compress the main body of the payload into a binary format using a schema-based compression like Protobuf, with additional metadata in readable JSON. That strikes the right balance between a well-known schema, reduced network calls and an optimally sized payload as well as providing the ability for subscribers to filter data.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;  &quot;metadata&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    &quot;eventType&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;orderCreated&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;  &quot;filters&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    &quot;orderValue&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt;256.82&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    &quot;geo&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;EN&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    &quot;customerAccountId&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;123456&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    &quot;deliveryType&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;PREMIUM&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;  &quot;payload&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;&amp;lt;BINARY_DATA_GOES_HERE&amp;gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;storage--analytics&quot;&gt;Storage &amp;amp; Analytics&lt;/h3&gt;
&lt;p&gt;Many of the concepts around compression discussed above apply equally to storage. The most important architectural consideration here is to &lt;strong&gt;understand your data access patterns&lt;/strong&gt;. Regardless of the storage technology you are using, understanding how the data is going to be accessed is vital in understanding how you can optimise.&lt;/p&gt;
&lt;p&gt;For example, let’s consider the use of DynamoDB as a primary data store. Used in the most efficient way, access to DynamoDB uses a combination of partition and sort keys. Any other data stored against an item isn’t available to query.&lt;/p&gt;
&lt;p&gt;In this scenario, leverage technologies like Protobuf to serialize the main bulk record to binary and store that in a more efficient way. An additional benefit here, you’ll probably reduce your costs as well.&lt;/p&gt;
&lt;p&gt;Considering your access patterns will also enable you to optimise the performance of your queries, having the knock on effect of optimising your compute. It’s a wonderful sustainability flywheel we are getting ourselves into, isn’t it?&lt;/p&gt;
&lt;p&gt;The other consideration around the data itself is what you store and how long you store it for. Continuously ask yourself the question about the data being stored and if all of it is necessary. And if it is, how long do you need to keep it around for?&lt;/p&gt;
&lt;p&gt;And finally, think about your recovery point objective and recovery time objective. Do you really need to be taking full database backups of your product review database every 5 minutes and storing them for up to 3 years? Probably not. Much like the compute option, fit the technology to the use case. There is no such thing as a one size fits all storage solution.&lt;/p&gt;
&lt;p&gt;Now some of these ideas become less useful when considering analytics. A nicely compressed piece of binary data is excellent for our storage costs and retrieval efficiency, not so useful for running custom analytics queries. How can we be pro-active about our analytics workloads?&lt;/p&gt;
&lt;p&gt;Unlike the compute recommendation of being reactive, only running applications when required, for analytics I would suggest being much more pro-active. Specifically, transform your data into a format that is suited for custom queries. Extract, transform, load (ETL) jobs have been around for a long time. One of my first jobs was developing ETL jobs. Using these pro-active mechanisms for pre-formatting data ensures that when these complex, custom queries come in, they are working in data sorted in the most efficient way.&lt;/p&gt;
&lt;p&gt;If you combine this with scheduling your ETL jobs to run during low-carbon intensive periods, you can really push up the sustainability of your analytics workloads.&lt;/p&gt;
&lt;h2 id=&quot;charachterize-observe-improve&quot;&gt;Charachterize. Observe. Improve&lt;/h2&gt;
&lt;p&gt;I wanted to close out with a very specific section on architectural thinking. All architectures comprise the architectural ‘-ilities’. These ilities are often at odds with each other and are at the core of the often heard phrase ‘it depends’.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;li&gt;Availability&lt;/li&gt;
&lt;li&gt;Reliability&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Maintainability&lt;/li&gt;
&lt;li&gt;Flexibility&lt;/li&gt;
&lt;li&gt;Configurability&lt;/li&gt;
&lt;li&gt;Personalizability&lt;/li&gt;
&lt;li&gt;Usability&lt;/li&gt;
&lt;li&gt;Portability&lt;/li&gt;
&lt;li&gt;Conformance to standards&lt;/li&gt;
&lt;li&gt;Efficiency&lt;/li&gt;
&lt;li&gt;Responsiveness&lt;/li&gt;
&lt;li&gt;Interoperability&lt;/li&gt;
&lt;li&gt;Upgradability&lt;/li&gt;
&lt;li&gt;Auditability&lt;/li&gt;
&lt;li&gt;Transactionality&lt;/li&gt;
&lt;li&gt;Adminstrability&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Sustainability (my addition)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, it’s difficult to combine performance and security. Increasing security typically means slower performance. If we consider sustainability to be a non-negotiable, that naturally makes some of the other ‘-ilities’ fall become clear as well. This is very much my opinion, but these are what I would consider the most important ilities for sustainability.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;li&gt;Security (it’s job zero, it makes it on to every list)&lt;/li&gt;
&lt;li&gt;Flexibility&lt;/li&gt;
&lt;li&gt;Usability&lt;/li&gt;
&lt;li&gt;Efficiency&lt;/li&gt;
&lt;li&gt;Interoperability&lt;/li&gt;
&lt;li&gt;Upgradability&lt;/li&gt;
&lt;li&gt;Auditability&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once we have defined the charachterisitics we want our system to have, we can use &lt;a href=&quot;https://www.thoughtworks.com/en-gb/insights/articles/fitness-function-driven-development&quot;&gt;fitness functions&lt;/a&gt; to ensure we have continual feedback for conformance to the core tenets of our system.&lt;/p&gt;
&lt;p&gt;For example, if scalability and efficiency are our core tenets to enable sustainability, we may write fitness functions to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Monitor resource usage and how optimally we are consuming the resources we have allocated to a task&lt;/li&gt;
&lt;li&gt;Monitor how often we are using compute when there is no work to be done&lt;/li&gt;
&lt;li&gt;Ensure no individual piece of compute runs for longer than 100ms, and uses more than 128mb of memory&lt;/li&gt;
&lt;li&gt;Monitor scaling behaviour, and how quickly our system adapts to demand&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fitness functions should run both as triggers, as part of CICD, and continually as part of ongoing system monitoring.&lt;/p&gt;
&lt;p&gt;For all of that to work, observability is another non-negotiable ‘-ility’ in all of our sustainable architectures. Generating trace and metrics data to understand our systems enables us to be data driven about how we optimise and gives our fitness functions something to work with.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;If you’ve stuck with it this far, thanks for reading. If I’ve lost you, well, you’ve probably not got this far anyway, so this sentence is becoming irrelevant.&lt;/p&gt;
&lt;p&gt;Frankly, this post has been a bit of a brain dump. A coming together of my technical skills and my values to want to inspire change in the world.&lt;/p&gt;
&lt;p&gt;I truly believe that as software practitioners, we have immense potential to bring about genuine change in the world.&lt;/p&gt;
&lt;p&gt;Let that carry into everything you do.&lt;/p&gt;
&lt;p&gt;James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Essentialism in Software</title><link>https://blog.jameseastham.co.uk/blog/essentialism-in-software/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/essentialism-in-software/</guid><description>In this blog post, I discusses the concept of Essentialism, which involves focusing all of your energy on one thing and doing it well. I explain how many of us tend to spread ourselves thin across multiple tasks, leading to a dissipation of our energy in different directions. I then make the case for how this concept can be applied to software development. They mention that in Domain Driven Design, Eric Evans discusses the idea of core, generic, and supporting subdomains, which can be leveraged to streamline and simplify software development. By applying the principles of Essentialism, developers and the software they build can prioritize what&apos;s truly important and avoid getting bogged down in unnecessary complexity.</description><pubDate>Fri, 31 Mar 2023 06:25:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;“The Way of the Essentialist involves doing less, but better, so you can make the highest possible contribution. The Way of the Essentialist isn’t about getting more done in less time. It’s not about getting less done. It’s about getting only the right things done.”&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://gregmckeown.com/books/essentialism/&quot;&gt;Greg McKeown&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://gregmckeown.com/books/essentialism/&quot;&gt;Essentialism&lt;/a&gt; is a book that I frequently revisit, typically at least once or twice per year. The core idea is to focus all of your energy on one thing and do it well, rather than spreading yourself thin across multiple tasks. This approach differs from the norm, where many of us tend to work on multiple things simultaneously, leading to a dissipation of our energy in different directions.&lt;/p&gt;
&lt;p&gt;This might be multi-tasking in the well known sense. Focused work, whilst checking email every couple of minutes and being distracted by constant Slack notifications. Or it might be the multi-tasking that sits slightly under the surface. The kind that has us working on multiple different projects, in multiple different disciplines at the same time.&lt;/p&gt;
&lt;p&gt;Having interests in multiple different areas is a great strategy, it allows us to cross-polinate ideas and solve problems in innovative ways. This is discussed at length in the excellent book &lt;a href=&quot;https://www.amazon.com/Range-Generalists-Triumph-Specialized-World/dp/0735214484&quot;&gt;Range&lt;/a&gt; by David Epstein. But a clear seperation helps our brains focus.&lt;/p&gt;
&lt;p&gt;I’ve been particularly guilty of this myself. In the past, I would sign up for any and everything that even remotely related to my interests. Learning to say no or delegate has been a tough lesson that I’ve had to learn in the last 18 months. While it may work for a little while, and you may achieve some success, it’s not a sustainable strategy. Saying yes to everything and attempting to advance multiple projects simultaneously inevitably results in little progress anywhere.&lt;/p&gt;
&lt;p&gt;Have one focus, commit fully, then move on to the next thing. The next idea. The next area of interest.&lt;/p&gt;
&lt;h2 id=&quot;essentialism-in-software&quot;&gt;Essentialism in software&lt;/h2&gt;
&lt;p&gt;You’re probably wondering how this relates to software. But there are some interesting ideas we can take from essentialism and apply it to the way we think about software.&lt;/p&gt;
&lt;p&gt;This isn’t a new idea. In Domain Driven Design, Eric Evans discusses core, generic, and supporting subdomains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Core: The unique selling point (USP) of your business, the thing that sets you out from your competitors and delights your custoemrs.&lt;/li&gt;
&lt;li&gt;Supporting: Areas of the system that are required for your core domain, but aren’t differentiating with the competition and there aren’t any off the shelf solutions available.&lt;/li&gt;
&lt;li&gt;Generic: Areas of the system that are completely undifferentiating.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Already, you can start to see how essentialism fits. As much as possible, the focus of a software organisation should be in the core domain. Improvement in this area, will have the most impact on your customers.&lt;/p&gt;
&lt;p&gt;Yet, even with this in mind I see many companies getting lost in supporting and generic subdomains forgetting the value they actually want to deliver to customers. They are expending energy in every possible direction, instead of a single minded focus.&lt;/p&gt;
&lt;h2 id=&quot;undifferentiated-heavy-lifting&quot;&gt;Undifferentiated Heavy Lifting&lt;/h2&gt;
&lt;p&gt;Werner Vogels, CTO of Amazon, is well known for talking about undifferentiated heavy lifting. The cloud enables you to shovel this work on to the cloud provider leaving you to focus on adding value. This is a big step towards essentilism. Gone are the days of racking servers and crossing your fingers that the backup generator kicks in quickly during a power cut.&lt;/p&gt;
&lt;p&gt;But even in the modern, &lt;em&gt;‘cloud native’&lt;/em&gt; world, there still seems to be an obsession with continuing to focus on this lifting. On these supporting and generic subdomains that your customers don’t care about. Yes, your customers care that your application is always accessible. They don’t care if you’re doing that with serverless compute or with a container orchestrator.&lt;/p&gt;
&lt;p&gt;Let’s stick with the container orchestrator idea for a moment. I don’t want this next section to feel like I’m shitting on Kubernetes and I fully appreciate there are valid use cases for a container orchestrator. But let’s compare and contrast with something like &lt;a href=&quot;https://aws.amazon.com/lambda/&quot;&gt;AWS Lambda&lt;/a&gt;, or if containers float your boat then &lt;a href=&quot;https://aws.amazon.com/apprunner/&quot;&gt;AWS AppRunner&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let’s consider this for a startup or early stage organisation trying to launch a new idea.&lt;/p&gt;
&lt;p&gt;Even when levearging managed services like &lt;a href=&quot;https://aws.amazon.com/eks/&quot;&gt;Amazon Elastic Kubernetes Service (EKS)&lt;/a&gt;, there is an awful lot of infrastructure management and configuration needed. This is before you even get the first MVP of your product in front of a customer.&lt;/p&gt;
&lt;p&gt;Comparing that with a service like AWS Lambda, where I can write a piece of code that focuses &lt;strong&gt;only&lt;/strong&gt; on my business logic, deploy that to the cloud and be confident it will scale when required. No infrastructure management, no setup beforehand. An unparalleled time to value.&lt;/p&gt;
&lt;h2 id=&quot;low-code-applications&quot;&gt;Low Code Applications&lt;/h2&gt;
&lt;p&gt;There is a step even a beyond Lambda and serverless compute. A step that enables applications to be built without a single line of application code. What application code requires the least amount of heavy lifting? Code that is never written.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://aws.amazon.com/step-functions/&quot;&gt;AWS Step Functions&lt;/a&gt; is my favorite AWS service. It offers direct integration with &lt;strong&gt;almost any&lt;/strong&gt; AWS service through its SDK integrations. By leveraging this capability, you can potentially build out large parts of your supporting and generic subdomains without writing a single line of application code. With no need for infrastructure management, configuration, or even updates to libraries and changes to code, your non-core subdomains become about as low lift as they could possibly be.&lt;/p&gt;
&lt;p&gt;If you’re interested, I have a &lt;a href=&quot;https://github.com/jeastham1993/event-driven-serverless-cdk&quot;&gt;repository on GitHub&lt;/a&gt; that implements a review translation and sentiment analysis service without a single line of application code. Or if video is your thing, my talk at the &lt;a href=&quot;https://www.youtube.com/watch?v=vNrFmsgVWNM&quot;&gt;AWS Community Summit 2022&lt;/a&gt; where I discuss this repository.&lt;/p&gt;
&lt;h2 id=&quot;the-essentilist-spectrum&quot;&gt;The Essentilist Spectrum&lt;/h2&gt;
&lt;p&gt;I’m not a purist, and appreciate there are absoloutely scenarios where greater control is required. GPU heavy workloads, developer familiarity, longer running workloads. This isn’t a debate about Kubernetes vs Lambda vs native service integrations. That was meant purely as an example.&lt;/p&gt;
&lt;p&gt;However, all of these ideas sit along a spectrum of essentialism. At each stage, you choose to introduce an additional pressure on the energy your organisation has to move forwards. To implement features. To delight your customers.&lt;/p&gt;
&lt;p&gt;This spectrum fits nicely with a &lt;em&gt;‘serverless first’&lt;/em&gt; mindset. My view on serverless first is quite simple. Default to as little undifferentiated heavy lifting as possible and increase as required. I would typically couple this with a view on core vs non-core subdomain.&lt;/p&gt;
&lt;p&gt;For example, if I am designing a new feature for a service that exists as a supporting sub domain I would go through:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Step Functions with native service integrations&lt;/li&gt;
&lt;li&gt;Lambda&lt;/li&gt;
&lt;li&gt;AppRunner&lt;/li&gt;
&lt;li&gt;Fargte on ECS&lt;/li&gt;
&lt;li&gt;EC2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can apply similar heuristics to areas outside of compute (DynamoDB vs RDS for example).&lt;/p&gt;
&lt;p&gt;I realise many decisions are a lot more nuanced, and jumping straight into the implementation details is not typically where I would begin. But once we are down in the weeds, I find this an excellent way to add business value whilst reducing operational overhead.&lt;/p&gt;
&lt;p&gt;Our software is essentialist.&lt;/p&gt;
&lt;p&gt;Thanks for reading,
James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Thinking in Patterns; The Importance of Language in Software Architecture</title><link>https://blog.jameseastham.co.uk/blog/thinking-in-patterns-language/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/thinking-in-patterns-language/</guid><description>Language is the foundation upon which all communication is built. It&apos;s how we share our thoughts, feelings and ideas with one another. And in the world of software, language is just as critical. How we talk about and describe the structures and patterns we use to build software can have a significant impact on the success of our projects.</description><pubDate>Fri, 24 Mar 2023 14:19:00 GMT</pubDate><content:encoded>&lt;p&gt;Language is the foundation upon which all communication is built. It’s how we share our thoughts, feelings and ideas with one another. And in the world of software, language is just as critical. How we talk about and describe the structures and patterns we use to build software can have a significant impact on the success of our projects.&lt;/p&gt;
&lt;p&gt;This becomes even more important when building serverless, event driven applications built up of small, loosely joined pieces of functionality. It’s like playing with LEGO bricks, but instead of creating a colorful spaceship, you’re constructing a well-oiled software machine. And we’ve all been there when we can’t quite understand how two pieces fit together. In this blog post, we’ll explore the importance of language in software architecture and how the words we use can shape the way we think.&lt;/p&gt;
&lt;h2 id=&quot;patterns-arent-a-new-thing&quot;&gt;Patterns Aren’t a New Thing&lt;/h2&gt;
&lt;p&gt;Software patterns aren’t a new concept. The famous &lt;a href=&quot;https://www.amazon.co.uk/Design-Patterns-Object-Oriented-Addison-Wesley-Professional-ebook/dp/B000SEIBB8&quot;&gt;‘gang of four’ published Design Patterns&lt;/a&gt; back in October 1994. Whilst focused on object-oriented programming languages like C# and Java, it provided terminology to help developers communicate with each other.&lt;/p&gt;
&lt;p&gt;If someone mentions the builder pattern to me, I understand what they are trying to achieve.&lt;/p&gt;
&lt;p&gt;It also aids the readability of code. If I jump into a new code base and see classes named &lt;code&gt;OrderFactory&lt;/code&gt; or &lt;code&gt;ConfigurationBuilder&lt;/code&gt; I have a rough idea of what the intended functionality of that object is without needing to work through multiple code files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Patterns reduce cognitive load, providing helpful guidance to our brains when processing new information&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There is a part of our brain (the neocortex for any fellow neuroscience nerds) that recognises patterns. The pattern recognition process involves matching information new information with information already stored in the brain. Using a common language aids that matching process, much like a memory pointer in programming.&lt;/p&gt;
&lt;p&gt;Following on from the Gang of Four book, &lt;a href=&quot;https://www.amazon.co.uk/Patterns-Enterprise-Application-Architecture-Addison-Wesley-ebook/dp/B008OHVDFM/ref=sr_1_1&quot;&gt;Patterns of Enterprise Application Architecture&lt;/a&gt; and &lt;a href=&quot;https://www.amazon.co.uk/Enterprise-Integration-Patterns-Designing-Addison-Wesley-ebook/dp/B007MQLL4E/ref=sr_1_1&quot;&gt;Enterprise Integration Patterns&lt;/a&gt; were both published in 2012. Both are brilliant books to have as a reference if you don’t have them sat on your bookshelf already.&lt;/p&gt;
&lt;p&gt;These books are a reference guide to help us talk about the systems we build. To give us a common language, a set of patterns that describe the systems we are building. Somehow, this got lost along the way.&lt;/p&gt;
&lt;h2 id=&quot;lost-in-a-sea-of-implementation-details&quot;&gt;Lost in a sea of implementation details&lt;/h2&gt;
&lt;p&gt;When was the last time you saw an architecture diagram or design that mentioned a channel adapter? Or using scatter-gather to meet our business use case. Instead, as architects, we default (and I’m guilty of this as much as anyone) to the implementation details. To the services sat underneath.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.jameseastham.co.uk/assets/architecture.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I pulled this diagram straight from a repository on my GitHub. For someone unfamiliar with AWS services, how would you understand what is going on here? You could establish there are 5 separate components, each made up of 2 or more individual pieces. Yes, you could deep dive into the code and try to work it out. But this diagram tells me nothing about my architecture, and everything about my implementation details.&lt;/p&gt;
&lt;p&gt;Both are important, of course. But we are missing a step. We are jumping straight to the implementation without considering what patterns we want to use.I have a particular liking for Amazon Event Bridge. If I need to communicate between 2 systems asynchronously, that’s my default. This is a bias I’m trying to break. So let’s explore this requirement in a little more detail.&lt;/p&gt;
&lt;p&gt;There are 2 systems that need to communicate asynchronously, which might seem like a pretty straightforward ask. Depending on biases you hold from systems you’ve worked on in the past, or what you’re most familiar with, you’ll probably end up with one of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Amazon EventBridge&lt;/li&gt;
&lt;li&gt;Amazon SNS&lt;/li&gt;
&lt;li&gt;Amazon SQS&lt;/li&gt;
&lt;li&gt;Amazon Kinesis&lt;/li&gt;
&lt;li&gt;Kafka&lt;/li&gt;
&lt;li&gt;RabbitMQ&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Other message broker/streaming/queuing system that allows components to be decoupled&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The question then becomes, which one do we pick? Comparing service to service at an implementation detail level will lead to a lot of confusion. It’s the most common question I get asked when talking about event driven architectures. What’s the difference between SNS &amp;amp; EventBridge? It’s confusing, right?&lt;/p&gt;
&lt;p&gt;There’s an easier way than getting lost in the features of a specific service, though. That’s through good communication and the use of patterns.&lt;/p&gt;
&lt;h2 id=&quot;a-better-way&quot;&gt;A Better Way&lt;/h2&gt;
&lt;p&gt;This is where communication is a vital tool in the toolbox of any architect. The answer to the question of ‘I need to communicate between 2 systems asynchronously, which service do I use?’ is, of course, another set of questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do you need to guarantee that only one receiver processes the message?&lt;/li&gt;
&lt;li&gt;Do you need to distribute the message to an unknown number of receivers?&lt;/li&gt;
&lt;li&gt;Do you want to keep each type of message on it’s own individual channel?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a bunch more questions we could ask here. But what began as a simple question that my bias told it could answer with Event Bridge turned out to not quite be that simple. And, in my hypothetical scenario, the business requirement is for strict ordering and a guarantee that only one receiver ever processes the message. My first decision was one that future James would not have thanked me for.&lt;/p&gt;
&lt;p&gt;Taking that same list of questions, we can apply a pattern which then leads to the right implementation detail falling out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do you need to guarantee that only one receiver processes the message?
&lt;ul&gt;
&lt;li&gt;Point to point channel / Amazon SQS&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Do you need to distribute the message to an unknown number of receivers?
&lt;ul&gt;
&lt;li&gt;Publish Subscribe / Amazon Event Bridge&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Do you want to keep each type of message on it’s own individual channel?
&lt;ul&gt;
&lt;li&gt;Message Channels / Amazon SNS&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Describing our architectures through the lens of patterns &amp;amp; requirements, as opposed to services, simplifies the communication between both existing and new developers. If I join a new team, and I’m told we have a point-to-point integration between these two services that guarantees only one receiver processes the message, I have learned an awful lot about the system function. If I’m shown an architecture diagram that contains a map of service icons, I’m up the creek of implementation details without a paddle.&lt;/p&gt;
&lt;h2 id=&quot;knock-on-affects&quot;&gt;Knock on Affects&lt;/h2&gt;
&lt;p&gt;There’s a more subtle benefit to thinking about systems in this way, and that’s one of bias. I might work for weeks on a well-architected system using specific AWS services only to be told that ‘You can’t use Event Bridge because the security team said so’. My architecture diagram falls to pieces. I might push back, or spend hours with the security team discussing what we can do to make Event Bridge available. This might be the right approach, but there’s also a pretty good chance it’s &lt;a href=&quot;https://thedecisionlab.com/biases/the-sunk-cost-fallacy&quot;&gt;sunk cost bias at play&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If I built my architecture diagram using patterns, instead of an Event Bridge service icon, there would be a ‘publish subscribe’ channel. Event Bridge isn’t usable, ok then let’s use SNS. The CTO mandates we must use non-AWS managed services, ok let’s substitute in Kafka or RabbitMQ.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.jameseastham.co.uk/assets/diagram.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;One might look prettier, but the second much more clearly demonstrates my intentions as an architect.&lt;/p&gt;
&lt;h2 id=&quot;think-in-patterns-not-in-services&quot;&gt;Think in Patterns, not in services&lt;/h2&gt;
&lt;p&gt;The risk here, is a re-introduction of the ivory tower architect. An architect who thinks in patterns and abstract concepts but never spends any time building. That is an important point to close this post. Think in patterns, design in patterns, but never lose that builder mindset. The balance is key in the world of software architecture.&lt;/p&gt;
&lt;p&gt;Thanks for reading,
James&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Business Logic First, Implementation Details Second</title><link>https://blog.jameseastham.co.uk/blog/business-logic-first-implementation-second/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/business-logic-first-implementation-second/</guid><description>Your business logic is what makes your application stand out. NoSQL vs SQL? Serverless vs containers? Neither of these decisions matter if your business logic doesn&apos;t work. Good design focuses on the business logic first.</description><pubDate>Sun, 21 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;start-with-why&quot;&gt;Start with why?&lt;/h2&gt;
&lt;p&gt;Have you ever made an implementation decision in an application that turned out to be incorrect? Have you ever got a ‘production ready’ system and realised you have no way to test it? If so, this post is for you.&lt;/p&gt;
&lt;p&gt;If I was to ask you what is it that makes your software systems stand out, what would you say? Would it be the fact your entire system runs on AWS Lambda? Or how about that you’ve got a custom built Kubernetes platform that developers can deploy to? NoSQL vs SQL?&lt;/p&gt;
&lt;p&gt;Of course, it’s none of these things. What makes your system stand out is its core features. What is the unique selling point that convinces your customers to choose your product over one of its competitors? It’s how quickly you can respond to the changing needs of your customers.&lt;/p&gt;
&lt;p&gt;Anything outside of these two points is an implementation detail:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What is the core domain of your system that makes it stand out from the crowd?&lt;/li&gt;
&lt;li&gt;How maintainable is it and how quickly can you respond to change?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Making a technology choice because everyone else is doing it is not a convincing reason to do anything. I learned that lesson the hard way. In a previous job, I spent days implementing Kafka to allow 5 loosely coupled services to run independently. It was an interesting technology to work with but, in hindsight, the whole thing would have run better as a monolith. Couple that with the fact I was the only one who understood Kafka, and the maintainability took a nosedive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In my attempts to reduce the coupling between the parts of my applications, I’d tightly coupled the parts to a more valuable resource. A single developer’s time.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I saw Kafka; I was interested in it, my developer magpie took over and I made an unsuitable implementation decision. I did that because it was interesting. I started from the technology choice, not from the problem space my application was solving.&lt;/p&gt;
&lt;p&gt;Serverless or containers? Kubernetes or Amazon ECS? Kafka or Amazon Kinesis?&lt;/p&gt;
&lt;p&gt;None of these decisions matter, at least in the short term.&lt;/p&gt;
&lt;p&gt;I am not advocating for big upfront design. What I am an advocate of is to start every new software project with your core business logic, forgetting all implementation details. Then let the code drive the design of your system components.&lt;/p&gt;
&lt;h2 id=&quot;design-with-code&quot;&gt;Design with code&lt;/h2&gt;
&lt;p&gt;What does it mean to do upfront thinking?&lt;/p&gt;
&lt;p&gt;Domain Driven Design (DDD) is one of the seminal books on software system design. Written by Eric Evans in August 2003 it should be at the top of the reading list for any architect or engineer.&lt;/p&gt;
&lt;p&gt;Amongst the many other concepts in DDD, one of the most useful is the concept of bounded contexts. A bounded context is a logical boundary around a part of your application. Note, this does not need to equal a separate micro-service. It could be a modular monolith.&lt;/p&gt;
&lt;p&gt;Each model within a bounded context exists only within that context. Take the simple example of an eCommerce application. The term product has several meanings based on who you speak to. In order processing, we care about the price and the quantity of an order. In inventory management, we care about stock levels.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.jameseastham.co.uk/assets/product-img.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Whilst these are the same product, conceptually they are different things in our application.&lt;/p&gt;
&lt;p&gt;If we were to dive straight in and start building this application, we may end up with a product class like this.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Product&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; ItemSKU { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Price { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; QuantityOrdered { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; QuantityInStock { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; QuantityOnPurchaseOrder { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; UpdateItemPrice&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; newPrice&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        //....&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; AddToPurchaseOrder&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; quantity&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        //....&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Ordered&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; quantityOnOrder&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        //....&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our product class now understands how to manage orders, purchasing and stock. Inevitably, this will lead us down a path of having one big Product class that controls our entire application.&lt;/p&gt;
&lt;p&gt;Understanding this up front is a vital part of software maintainability.&lt;/p&gt;
&lt;p&gt;We could approach this problem by spending days talking about the system, whiteboarding and drawing up design documents. Whilst this would work, a lot of problems don’t appear until code is written.&lt;/p&gt;
&lt;p&gt;There’s a two-step process to get around this, that doesn’t require a lot of designing. A way that gets you writing code quickly whilst not committing down any specific path:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start with your core business logic, leave all implementation details until the last possible moment&lt;/li&gt;
&lt;li&gt;Practice test driven development&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;start-with-your-core-business-logic&quot;&gt;Start with your core business logic&lt;/h3&gt;
&lt;p&gt;Code becomes infinitely more difficult to refactor once you introduce a dependency. Whether that be a database technology, messaging system or a compute provider. At first, only write ‘pure’ business logic code.&lt;/p&gt;
&lt;p&gt;Remember, it’s your business logic that is your key differentiator. Getting this right and making it maintainable is going to have a tangible effect on the success of your system.&lt;/p&gt;
&lt;p&gt;Going back to our product class for a moment. Writing that code, you may realise that the product class is doing too much. If you had already tied that to a database implementation change becomes difficult. If it is pure business code with any implementations hidden behind well-defined abstractions, change becomes easier.&lt;/p&gt;
&lt;p&gt;Seeing this may make you realise that you have a boundary. A product is conceptually different things based on the context it is in. So let’s split that into a separate module.&lt;/p&gt;
&lt;p&gt;This strikes the perfect balance. You are getting hands on and writing actual code. No amount of white boarding provides a better way of understanding your problem space. However, it leaves flexibility to change direction.&lt;/p&gt;
&lt;h3 id=&quot;test-driven-development&quot;&gt;Test Driven Development&lt;/h3&gt;
&lt;p&gt;Hand in hand with this approach is test driven development. As you change and develop your core domain, you want to ensure you aren’t breaking any functionality. Practicing test driven development gives you that safety net to change your code whilst ensuring you aren’t breaking any functionality.&lt;/p&gt;
&lt;p&gt;Writing code that is testable has the added benefit of producing code that is maintainable.&lt;/p&gt;
&lt;p&gt;Let’s imagine you dive straight in and use AWS Lambda because all the cool kids are doing it. We may end up implementing a Lambda function that looks something like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;FunctionHandler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;APIGatewayProxyRequest&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; apigProxyEvent&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;IsNullOrEmpty&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;apigProxyEvent&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Body&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;            // Handle HTTP response...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; command&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; JsonSerializer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Deserialize&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreateProductCommand&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;apigProxyEvent&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Body&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;IsNullOrEmpty&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ItemSKU&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Price&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; &amp;lt;=&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            throw&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ArgumentException&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Invalid command&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; product&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Product&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ItemSKU&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Price&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        using&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; connection&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;SqlConnection&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;CONNECTION_STRING&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        using&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; command&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;SqlCommand&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;connection&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;connection&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;OpenAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ExecuteNonQueryAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;				// Additional business logic to update the product quantity in stock...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        // Additional business logic to create an initial purchase order...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        // Handle HTTP response...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code may be functional, but how would you test it? We tied the implementation details up with our business logic, making it almost impossible to test without standing up additional infrastructure.&lt;/p&gt;
&lt;p&gt;The second problem with this is that we are now tied to an implementation detail. Here, AWS Lambda. What if we discover during development that the business logic to create a purchase order takes 20 minutes? Given AWS Lambda has a 15 minute timeout, it is unsuitable. But our code is so coupled with the intricacies of Lambda, how would we move away?&lt;/p&gt;
&lt;p&gt;If we had approached this differently and started with the business logic, it may have looked like this.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CreateProductCommandHandler&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; IProductRepository&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; _productRepository&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; IInventoryService&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; _inventoryService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; IPurchasing&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; _purchasingService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; CreateProductCommandHandler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IProductRepository&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; productRepository&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IInventoryService&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; inventoryService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IPurchasing&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; purchasingService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        _productRepository&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; productRepository&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        _inventoryService&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; inventoryService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        _purchasingService&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; purchasingService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Product&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreateProductCommand&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;IsNullOrEmpty&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ItemSKU&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Price&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; &amp;lt;=&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            throw&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ArgumentException&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Invalid command&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; product&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Product&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ItemSKU&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Price&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_productRepository&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Create&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;product&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_inventoryService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;UpdateInventory&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;product&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_purchasingService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;CreatePurchaseOrder&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;product&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; product&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We now have a core piece of business logic that has no dependencies on anything outside of our code base. This code is easily testable, we can inject mock implementations of our interfaces and use that to understand how different inputs flow through our logic. It also allows us to easily express the intent of our business logic. For anyone reading this who isn’t a .NET developer, I’m sure you can still grasp what the intention of the code.&lt;/p&gt;
&lt;p&gt;Test Driven Development won’t solve all our problems. After implementing this, we may still end up committing to AWS Lambda before realising in production that our purchasing service takes 20 minutes. It doesn’t matter though, Lambda is an implementation detail. All our Lambda function is doing is handling the intricacies of Lambda before handing the actual work off to our business logic.&lt;/p&gt;
&lt;p&gt;This provides an un-paralleled level of flexibility. Here is my create product process running 3 different hosting options.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lambda&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; static&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CreateProductCommandHandler&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; _handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Function&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;() : &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    internal&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Function&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreateProductCommandHandler&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        _handler&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; ?? new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreateProductCommandHandler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;SqlProductRepository&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(), new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IInventoryService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(), new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;PurchasingService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;FunctionHandler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;APIGatewayProxyRequest&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; apigProxyEvent&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;IsNullOrEmpty&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;apigProxyEvent&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Body&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;            // Handle HTTP response...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; command&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; JsonSerializer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Deserialize&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreateProductCommand&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;apigProxyEvent&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Body&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; createdProduct&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_handker&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Handle&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        // Handle HTTP response...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;ASP.NET Web API&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ApiController&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Route&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;[controller]&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; ProductController&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ControllerBase&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CreateProductCommandHandler&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; _handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; ProductController&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreateProductCommandHandler&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        _handler&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;HttpPost&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(Name &lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;CreateProduct&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Product&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;CreateProduct&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;([&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;FromBody&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreateProductCommand&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; createdProduct&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; createdProduct&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Console Application&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; handler&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreateProductCommandHandler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;SqlProductRepository&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(), new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IInventoryService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(), new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;PurchasingService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;What is the item SKU?&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; itemSku&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ReadLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;What is the price?&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; price&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Parse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ReadLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; command&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreateProductCommand&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;itemSku&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;price&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;handler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Handle&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;command&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Product created&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’ll notice the only difference is the specific requirements of the technology. Lambda requires us to parse the HTTP request. ASP.NET takes away a lot of boilerplate and the console app requires us to read data from console inputs.&lt;/p&gt;
&lt;p&gt;We can run the same code in 3 different compute options with 0 changes to our business logic. Code that isn’t changed has a much higher chance of stability. Our code is maintainable, flexible and resilient to changes in technology. And one thing that is certain in technology is that things will change.&lt;/p&gt;
&lt;p&gt;Writing software in this way makes your core business logic, your unique selling point, more resistant to that change. Who wouldn’t want more of that?&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Event Modeling By Example</title><link>https://blog.jameseastham.co.uk/blog/event-modelling-by-example/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/event-modelling-by-example/</guid><description>A look at the process of event modeling when designing software through the lens of a restaurant management application.</description><pubDate>Wed, 21 Jul 2021 22:12:03 GMT</pubDate><content:encoded>&lt;p&gt;Good design is a fundamental thing for me when it comes to building applications. Yes, there is a time in a place for a quick functional program that does a simple job ala scheduled batch file. But in almost all cases, committing even a small amount of time to thoughtful design has huge ramifications on the long-term success of a project.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Design for where you want your application to be, not where it is now&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;An element of this is the principles of Domain-Driven Design (DDD). For those who aren’t aware, DDD is the name of a book written by Eric Evans in 2003 detailing a methodology for designing software. At its core, it maps business domain concepts into software artifacts.&lt;/p&gt;
&lt;p&gt;Whilst I can heartily recommend the &lt;em&gt;big blue book&lt;/em&gt;, I did find it difficult to take practical steps that I can use when working with clients in the real world. That is where event modeling comes in.&lt;/p&gt;
&lt;h2 id=&quot;introduction-to-event-modeling&quot;&gt;Introduction to event modeling&lt;/h2&gt;
&lt;p&gt;Event Modeling is a term coined by &lt;a href=&quot;https://eventmodeling.org&quot;&gt;Adam Dymitruk&lt;/a&gt;. It builds upon a lot of the concepts set out in DDD. The main focus is on the events that happen in a business, as all software is at the core is a series of events happening one after another.&lt;/p&gt;
&lt;p&gt;If the software focuses on things that the business can understand, the system can be easily understood by anybody looking at it. That includes everyone from C suite execs through the development team and even to customer service representatives with no background in IT.&lt;/p&gt;
&lt;p&gt;There are some fantastic resources on Adam’s website &lt;a href=&quot;https://eventmodeling.org&quot;&gt;https://eventmodeling.org&lt;/a&gt;, but what I wanted to-do today was walk through my process for implementing event modeling in a ‘real’ application.&lt;/p&gt;
&lt;h2 id=&quot;step-by-step&quot;&gt;Step by Step&lt;/h2&gt;
&lt;p&gt;Before I dive into the step-by-step, I want to identify a couple of tools and resources I use for this process.&lt;/p&gt;
&lt;p&gt;The first is the article on Adam’s website on &lt;a href=&quot;https://eventmodeling.org/posts/what-is-event-modeling/&quot;&gt;‘What is event modeling’&lt;/a&gt;. It adds a lot of context to the steps I’m going to follow in this article. I can recommend going to read that article before continuing with this one.&lt;/p&gt;
&lt;p&gt;The second is &lt;a href=&quot;https://miro.com&quot;&gt;Miro&lt;/a&gt;. Miro is a virtual whiteboard that allows multiple people to collaborate on the same board. Given more and more of the world is moving to a completely remote way of working, it’s an invaluable tool when it is simply impossible to all stand at a physical whiteboard.&lt;/p&gt;
&lt;p&gt;Even if you do use a physical whiteboard initially, it’s a great idea to move that to a digital tool for future developments. Online, backed up, and accessible anywhere - what’s not to love.&lt;/p&gt;
&lt;p&gt;So now, on to the steps.&lt;/p&gt;
&lt;h3 id=&quot;brainstorming&quot;&gt;Brainstorming&lt;/h3&gt;
&lt;p&gt;The first step of the process is to brainstorm ALL of the events that affect within the business domain being modeled. It’s important to have stakeholders from &lt;strong&gt;all&lt;/strong&gt; parts of the business in this session as each may have a valuable piece of insight into the workflows.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://jameseastham.co.uk/static/images/event-modeling-by-example/brain-storm.PNG&quot; alt=&quot;virtual post-it notes showing events&quot;&gt;&lt;/p&gt;
&lt;p&gt;What you are looking for here is just a brain dump of all the things happening in the business. There is no need to organize or categorize at this stage, just get it all out there. Remember, an event is always in the past tense. SubmitOrder is not an event but OrderSubmitted is.&lt;/p&gt;
&lt;h3 id=&quot;timeline&quot;&gt;Timeline&lt;/h3&gt;
&lt;p&gt;The second step is the first layer of organisation. All of the events should be added to a timeline that shows the journey through the system.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://jameseastham.co.uk/static/images/event-modeling-by-example/timeline.PNG&quot; alt=&quot;virtual timeline&quot;&gt;&lt;/p&gt;
&lt;p&gt;For anyone who has ever ordered food online, this series of events should be familiar.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;OrderSubmitted&lt;/li&gt;
&lt;li&gt;StockChecked&lt;/li&gt;
&lt;li&gt;PaymentProcessed&lt;/li&gt;
&lt;li&gt;OrderCooked&lt;/li&gt;
&lt;li&gt;OrderDispatched&lt;/li&gt;
&lt;li&gt;OrderDelivered&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The other thing you’ll notice on this diagram is that I’ve identified a couple of important events. These events are the ones that are fundamental to the business. In this example, taking payments and delivering orders are the two things needed for the restaurant to succeed.&lt;/p&gt;
&lt;h3 id=&quot;storyline&quot;&gt;Storyline&lt;/h3&gt;
&lt;p&gt;The third phase is to begin thinking about user interactions and the different people taking part in the process. Wireframe mockups are a great tool. These mock-ups don’t need to be concrete though they are just to give a rough idea of the interactions with the system.&lt;/p&gt;
&lt;p&gt;I find it helpful to split these down into swimlanes for the different people/systems who affect the system. It would also include any external systems (payment processors, CRM systems) that change state, albeit without direct human intervention.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://jameseastham.co.uk/static/images/event-modeling-by-example/story-line.PNG&quot; alt=&quot;storyline of event flow with wire frames&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this example, I’m more concerned about the backend application than the look of the frontend. For that reason, I’ve just included some icons to indicate there will be interactions from either a UI or an external system.&lt;/p&gt;
&lt;p&gt;Notice how I’ve included the cog icons for the stock checker and payment processor. It shows that there is a process that happens to cause a change in the system state. The interaction may not be driven by a human, but it is an interaction all the same.&lt;/p&gt;
&lt;h3 id=&quot;interactions&quot;&gt;Interactions&lt;/h3&gt;
&lt;p&gt;Phase four is where things start to get interesting. It is where I begin to link the UI/UX to the events via commands.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://jameseastham.co.uk/static/images/event-modeling-by-example/interactions.PNG&quot; alt=&quot;storyline of event flow commands included&quot;&gt;&lt;/p&gt;
&lt;p&gt;Taking the first workflow as a specific example:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A customer interacts with a UX screen that allows them to make an order&lt;/li&gt;
&lt;li&gt;The UX sends a SubmitNewOrder command&lt;/li&gt;
&lt;li&gt;A OrderSubmitted event is raised&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Taking a look at the whiteboard now, there is a clear flow from left to right. This interaction submits this command then this event happens.&lt;/p&gt;
&lt;p&gt;It can be beneficial at this point to talk about the command contents. Thinking about what makes up a SubmitStockCheckResults command can help to identify any missing data from earlier in the process.&lt;/p&gt;
&lt;h3 id=&quot;informing-the-users&quot;&gt;Informing the users&lt;/h3&gt;
&lt;p&gt;Phase five is where I start to look at the information users need to make decisions.&lt;/p&gt;
&lt;p&gt;I do this using bespoke read models that project the event information into a useful format for users. You can see these below on the green post-it notes.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://jameseastham.co.uk/static/images/event-modeling-by-example/views.PNG&quot; alt=&quot;storyline of event flow read model included&quot;&gt;&lt;/p&gt;
&lt;p&gt;For the stock checker to reliably check the stock of orders, it needs a view of all the orders that are currently waiting to have their stock checked. For the kitchen to cook the orders, they need to see a list of all the orders that have been paid and are awaiting production.&lt;/p&gt;
&lt;p&gt;Again, it’s important to not get bogged down in details here. It doesn’t matter if you’re using a queue, an event stream, or a relational database.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What matters is that the data needs to be exposed in a friendly format that can be used to make informed decisions about the system.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Adam refers to these read models as to-do lists, and I quite like that idea. A to-do list is a concept that almost everybody can understand. If I were to start talking about queues or a messages bus I would likely alienate the non-technical folk.&lt;/p&gt;
&lt;p&gt;The system is saying here are some data items that need to have an action performed on them.&lt;/p&gt;
&lt;p&gt;I find it’s at this stage that any holes start to become apparent. For example, in the above screenshot, a SubmitPaymentResult command happens results in a PaymentProcessed event. This event has a PaymentSuccess field that looks like it should be conditional in the workflow.&lt;/p&gt;
&lt;p&gt;When a PaymentProcessed event happens the order is placed on the OrdersAwaitingCook to-do list. But what if the payment fails?&lt;/p&gt;
&lt;p&gt;And this is where the value of event modeling becomes apparent. You have got a room full of people, both technical and not, who can talk the same language and rationalize about the behavior of the system.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Architect: &quot;So, what happens when the payment is processed but it fails for some reason?&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Mark in Order Processing: &quot;Oh, if that happens I would just notify the customer to inform them that their payment has failed.&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Architect: &quot;Ok, so how would that interaction happen?&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Barbara in Customer Service: &quot;Well, if the customer was stood in-front of me in the restaurant I could ask them to change their payment method. If they are ordering online, then I need them to know about the failure instantly so they can change their order, or at least know that they aren&apos;t going to be getting a pizza delivered.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In a matter of moments, I have learned something about our domain and can amend the flow of events on the fly. In the first iteration of the timeline, I processed payments and then added all orders to the OrdersAwaitingCook to-do list. Now, I have a small branch at this point in the case of an order failing.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://jameseastham.co.uk/static/images/event-modeling-by-example/views-v2.PNG&quot; alt=&quot;refactored storyline with views including payment failure&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;service-grouping&quot;&gt;Service grouping&lt;/h3&gt;
&lt;p&gt;Almost there now.&lt;/p&gt;
&lt;p&gt;The penultimate stage is to group the events into their service layers. Hopefully by this stage, you should start to see some pretty logical boundaries between the different events in your system.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://jameseastham.co.uk/static/images/event-modeling-by-example/service-layers.PNG&quot; alt=&quot;event flow with service groupings&quot;&gt;&lt;/p&gt;
&lt;p&gt;An important note here, these service layers should be based on the business domain and &lt;strong&gt;NOT&lt;/strong&gt; on a perceived microservices architecture. Remember, you are trying to keep everybody interested and on the same page.&lt;/p&gt;
&lt;p&gt;It can be good at this stage to think about the make-up of teams. A team of people, technical and non-technical, can now begin work on an individual service layer. These service layers can then develop independently, but the shared vision is also well understood.&lt;/p&gt;
&lt;p&gt;Yep, it sounds a lot like microservices. Resist the temptation, don’t say the word!&lt;/p&gt;
&lt;h3 id=&quot;scenarios&quot;&gt;Scenarios&lt;/h3&gt;
&lt;p&gt;The final stage is to build specific scenarios out of the workflows. A scenario is a user story that is built from this set of events, commands, and views.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://jameseastham.co.uk/static/images/event-modeling-by-example/scenarios.PNG&quot; alt=&quot;a view of different system scenarios / workflows&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now what I have is a list of very specific functional requirements that when pieced together form the basis of the entire system. Each of these individual workflows can be assigned to a specific team and that is the workflow they own.&lt;/p&gt;
&lt;p&gt;From here, a more developer-specific specification may be created in the form of a more traditional user story. What is important however, is that this event model is treated as the source of truth that the &lt;strong&gt;ENTIRE ORGANISATION&lt;/strong&gt; can understand.&lt;/p&gt;
&lt;p&gt;The development teams may have epics in Jira or cards on a Trello board. It’s largely irrelevant. The importance is the common language the entire system shares and can be used to rationalize different scenarios.&lt;/p&gt;
&lt;h2 id=&quot;additional-notes&quot;&gt;Additional Notes&lt;/h2&gt;
&lt;p&gt;There are a couple of additional bits of information that I just wanted to tack on at the end to answer some questions I know I had when I first encountered this model.&lt;/p&gt;
&lt;h3 id=&quot;implementation-is-irrelevant&quot;&gt;Implementation is irrelevant&lt;/h3&gt;
&lt;p&gt;If there is one I would take away from this, it is that the implementation is irrelevant. Whether that’s database providers, to-list implementations, programming languages. Don’t worry about any of it.&lt;/p&gt;
&lt;p&gt;The end goal should be for somebody non-technical and unfamiliar with the business to be able to understand what happens within the organisation very quickly.&lt;/p&gt;
&lt;p&gt;Imagine starting work at a new company. In your first day, you understand the entire system at a high level and begin to ask questions of both domain experts and developers in a language everybody understands. It wouldn’t matter if you were working in a technical or non-technical role.!&lt;/p&gt;
&lt;h3 id=&quot;slas-can-be-important&quot;&gt;SLA’s can be important&lt;/h3&gt;
&lt;p&gt;Whilst the implementation is irrelevant it can be useful to note on the diagram any time-sensitive operations.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://jameseastham.co.uk/static/images/event-modeling-by-example/sla.PNG&quot; alt=&quot;a view of different system scenarios / workflows&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can see I’ve marked very explicitly there is a business-specific rule that a stock check must complete in 10 seconds. This is to provide feedback to a user in real-time when they are using the application.&lt;/p&gt;
&lt;p&gt;Remember the detail of ‘real-time’ information isn’t important (SignalR, websockets, emails, etc), it is just that there is some form of service level agreement that the system needs to adhere to.&lt;/p&gt;
&lt;h3 id=&quot;wireframing&quot;&gt;Wireframing&lt;/h3&gt;
&lt;p&gt;The wireframes on all of my screenshots are icons taken from Miro’s built-in icon sets. My intention with this document is to show the backend architecture of a system using event modeling. I didn’t want to get too bogged down in front-end appearance. At least at this stage.&lt;/p&gt;
&lt;p&gt;In a normal working session, these wireframes would be drawn up to look like how you’d actually want the UI to look. If the UI was going to have three inputs, a dropdown, and a button go ahead and create a wireframe in Miro that looks like that.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;I hope you’ve found this step-by-step useful and that it has given you a good introduction to the concept of event modeling.&lt;/p&gt;
&lt;p&gt;I know it’s something I’ll be using in future architecture discussions as another tool to bridge the gap between business domain and technical details.&lt;/p&gt;
&lt;p&gt;A huge thanks to Adam Dymitruk for sharing so much information about this process. There is an abundance of YouTube videos out there containing real-world scenarios that Adam works through with businesses.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://miro.com/app/board/o9J_l5lypvI=/&quot;&gt;Miro Board used in this example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://eventmodeling.org/posts/what-is-event-modeling/&quot;&gt;https://eventmodeling.org/posts/what-is-event-modeling/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://eventmodeling.org/posts/event-modeling-cheatsheet/&quot;&gt;https://eventmodeling.org/posts/event-modeling-cheatsheet/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=SqaDYwgQ664&amp;amp;feature=youtu.be&quot;&gt;Event Modeling with Adam Dymitruk at the DDD Greece Meetup&lt;/a&gt;&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Serverless Redefined</title><link>https://blog.jameseastham.co.uk/blog/serverless-redefined/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/serverless-redefined/</guid><description>A look at serverless applications, and how this stretches beyond simple functions running in the cloud.</description><pubDate>Sun, 11 Jul 2021 11:43:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;“Serverless is a way to describe the services, practices, and strategies that enable you to build more agile applications so you can innovate and respond to change faster. With serverless computing, infrastructure management tasks like capacity provisioning and patching are handled by AWS, so you can focus on only writing code that serves your customers.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;em&gt;Definition of serverless, taken from &lt;a href=&quot;https://aws.amazon.com/serverless/&quot;&gt;AWS&lt;/a&gt;&lt;/em&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For a long time, I had quite a close-minded view of Serverless. I made heavy use of AWS Lambda and DynamoDB and stitched it all together using an API Gateway. Development productivity was through the roof, life was great.&lt;/p&gt;
&lt;p&gt;Until it wasn’t.&lt;/p&gt;
&lt;p&gt;I was working on a new project which had an extremely variable load (it could go for weeks without being used) but still needed really low latency when it was accessed.&lt;/p&gt;
&lt;p&gt;Lambda is great and with provisioned concurrency enabled it was ok from a latency perspective, but the business wanted more. I was out of ideas.&lt;/p&gt;
&lt;p&gt;My close-minded view of Serverless kept me banging my head against a wall of cold starts and application tracing to try and eek out as much performance as possible. It was a frustrating time. I knew Lambda was fantastic but couldn’t quite meet the requirements of the customer.my def&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://jameseastham.co.uk/static/images/Serverless%20Application%20Architecture.png&quot; alt=&quot;First version of Serverless Architecture Diagram&quot;&gt;
&lt;em&gt;Initial simplified architecture&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-change-in-approach&quot;&gt;A change in approach&lt;/h2&gt;
&lt;p&gt;That changed when I listed to an AWS podcast episode, specifically &lt;a href=&quot;https://aws.amazon.com/podcasts/448-aws-copilot-modern-applications-cli/&quot;&gt;episode #448&lt;/a&gt; talking about AWS Copilot. It struck me for two reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I’ve always been a big fan of ECS, but the cluster configuration, networking and general management was always a blocker. I’ll openly admit networking and server management is a weak part of my skillset, and I’ve never learnt. Deploying from a CLI to an AWS best practice environment removes that blocker completely.&lt;/li&gt;
&lt;li&gt;There is more to Serverless than AWS Lambda.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And it’s the second point that really struck me, there is more than one way to deploy an application in a serverless environment. I’m looking at you Fargate, and you App Runner.&lt;/p&gt;
&lt;p&gt;Taking a line of text directly from the Copilot documentation - &lt;em&gt;Request-Driven Web Service An AWS App Runner service that auto scales your instances based on incoming traffic and scales down to a baseline instance when there’s no traffic. This option is more cost-effective for HTTP services with sudden bursts in request volumes or low request volumes.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Sudden bursts in request volumes or low request volumes - Doesn’t that just sound like exactly what I am looking for?&lt;/p&gt;
&lt;p&gt;So what does that give me? It provides a way for me to easily deploy an application that is ‘always-on’ from an easy-to-use CLI, without the need to worry too much about the underlying infrastructure.&lt;/p&gt;
&lt;p&gt;This is when my definition of Serverless changed, and when the opening AWS quote made a lot more sense. Now I’d define Serverless as&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Any managed service that abstracts away operational complexity and allows developers and architects to focus on business value”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;From AWS Lambda to Azure Functions to Heroku. All of these services provide a platform that removes a barrier for developers and allows them to just get their code out into the wild.&lt;/p&gt;
&lt;p&gt;At a higher scale, there may be an argument for more fine-grained control. But for early startups and small companies, I cannot think of a better and more streamlined way of getting your product out there.&lt;/p&gt;
&lt;h2 id=&quot;a-change-in-architecture&quot;&gt;A change in architecture&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://jameseastham.co.uk/static/images/revamped-serverless-architecture.png&quot; alt=&quot;Serverless Architecture Diagram&quot;&gt;&lt;/p&gt;
&lt;p&gt;Whilst there isn’t anything different at first glance, there is one really important distinction.&lt;/p&gt;
&lt;p&gt;That distinction is AWS App Runner replacing the Lambda function that is handling client requests.&lt;/p&gt;
&lt;p&gt;For people unfamilar with &lt;a href=&quot;https://aws.amazon.com/apprunner/&quot;&gt;AWS App Runner&lt;/a&gt;, it’s a fully managed way of running containers in AWS without the need for managing underlying servers. You simply configure the required amount of CPU and memory and off you go.&lt;/p&gt;
&lt;p&gt;The rest of the architecture is identical. Any asynchronous event-driven tasks are still handled by Lambda. This feels like the use case for which Lambda was originally intended. A set of decoupled event handlers that sit doing nothing (and costing little money) until an event happens they are interested in that they react to accordingly.&lt;/p&gt;
&lt;p&gt;What this means for the system, is that end users get a low latency API response no matter when they access the app. An App Runner task is ‘always on’ in the same way that running a server would be.&lt;/p&gt;
&lt;p&gt;The trade-off here is an increase in cost, in that App Runner is charged per hour. The cost differs slightly when your application is actually processing requests vs sitting and waiting for a request to arrive. For a REST API, that is 24 hours a day 365 days a year. Slightly different than the Lambda model.
And what it comes down to is the age-old response of ‘it depends’. Everything depends on the use case.&lt;/p&gt;
&lt;p&gt;Lambda is a completely viable way to run an entire application, as long as a higher latency on the initial startup is ok. For high-volume API’s, this is probably not an issue as the functions will always be warm.&lt;/p&gt;
&lt;p&gt;However, for my specific use case of a low usage low latency application, the cost trade-off is something we are willing to accept to ensure the end-users have the best possible experience.&lt;/p&gt;
&lt;p&gt;The customer always comes first.&lt;/p&gt;
&lt;p&gt;For future applications, especially applications built in an event-driven fashion, this is becoming my de-facto architecture. Fargate / AWS App Runner for the client-facing applications, Lambda for the backend services that are less latency driven and more event-driven.&lt;/p&gt;
&lt;h2 id=&quot;in-practice&quot;&gt;In Practice&lt;/h2&gt;
&lt;p&gt;Now for a quick example of just how easy it is to get started with AWS Copilot and AppRunner. For that, I’m going to use the order management service in my &lt;a href=&quot;https://github.com/jeastham1993/node-restaurant&quot;&gt;node-restaurant&lt;/a&gt; repository.&lt;/p&gt;
&lt;p&gt;Originally, this application was built entirely from lambda functions. The REST API now runs as an express.js application, with any background event handlers running in Lambda. I already had a Dockerfile that I used for some local testing, so I can wire copilot up using that as well. So to get started with copilot, I simply run.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;copilot&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; init&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The CLI gives a really great step by step walkthrogh, for reference I selected:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Request Driven Web Service&lt;/li&gt;
&lt;li&gt;Name the application (order-api) &lt;em&gt;Important note, AppRunner has a max length on the name field which is the application name plus the service name&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Select the Dockerfile (helpfully, copilot defaults as it’s the only one I have)&lt;/li&gt;
&lt;li&gt;Yes to the test environment&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After a minute or two you should start to see the output from the Docker build command and then the beginning of the deployment. A note here, the first time you push out to AppRunner it does take quite a while to provision the infrastructure. Go grab a coffee or something and come back later.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;✔ Proposing infrastructure changes for stack node-restaurant-test-order-api&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- Creating the infrastructure for stack node-restaurant-test-order-api            [create complete]  [317.2s]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - An IAM Role for App Runner to use on your behalf to pull your image from ECR  [create complete]  [17.9s]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - An Addons CloudFormation Stack for your additional AWS resources              [create complete]  [28.7s]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - An IAM role to control permissions for the containers in your service         [create complete]  [17.9s]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - An App Runner service to run and manage your containers                       [create complete]  [285.9s]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once complete, head off to the App Runner UI, and voila the API is ready to serve requests.&lt;/p&gt;
&lt;p&gt;To come back around to my earlier point, everything always depends! There are benefits and trade-offs to every service, both AWS Lambda and App Runner are suitable for hosting an application. It just depends on the customer use case.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Front End for the .NET Developer with Blazor Web Assembly</title><link>https://blog.jameseastham.co.uk/blog/blazor-for-the-dotnet-developer/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/blazor-for-the-dotnet-developer/</guid><description>Throughout my entire development career, I&apos;ve always found web to be the best way of deploying an interface to any software I&apos;ve written. This posts dives into using Blazor for web development in .NET.</description><pubDate>Sun, 23 Feb 2020 17:47:43 GMT</pubDate><content:encoded>&lt;p&gt;Throughout my entire development career, I’ve always found web to be the best way of deploying an interface to any software I’ve written.&lt;/p&gt;
&lt;p&gt;Desktop never really appealed to me, maybe that comes from growing up almost entirely in an age where everything was web-based.&lt;/p&gt;
&lt;p&gt;However, coming from a .NET background, there are some downsides to this web-first approach.&lt;/p&gt;
&lt;p&gt;ASP Web Forms were ok, and MVC built upon that a little bit. But nothing ever really came close to the magic of the big Javascript frameworks.&lt;/p&gt;
&lt;p&gt;That lead me down a rabbit hole I never truly got to grips with, the magical world of Angular and React.&lt;/p&gt;
&lt;p&gt;I’ve toyed with both, completed tutorials and written production apps. Still, neither of them really clicked fully (I did massively prefer React, but that’s a personal preference thing).&lt;/p&gt;
&lt;p&gt;Typescript improved upon this pain slightly, bringing strong typing and a more C#-esque way of development.&lt;/p&gt;
&lt;p&gt;And then, along came Blazor…&lt;/p&gt;
&lt;h1 id=&quot;blazor&quot;&gt;Blazor&lt;/h1&gt;
&lt;p&gt;I’m not going to dive into too much detail around Blazor, there is plenty of other articles around the web regarding that (the &lt;a href=&quot;https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor&quot;&gt;official docs&lt;/a&gt; are a great place to start).&lt;/p&gt;
&lt;p&gt;To quickly summarise though, Blazor is Microsoft’s challenge to the big JS-based front end frameworks. It allows rich and interactive front end apps to be written entirely in C#. Not a line of Javascript insight.&lt;/p&gt;
&lt;p&gt;And with that, let’s dive into some code.&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;To get started with Blazor, I’m going to add a front end to the team-service I’ve been building throughout this series of articles. It’s a learning process for me as well, so stay with me!&lt;/p&gt;
&lt;p&gt;Running the below commands is all it takes to get started with a new Blazor app.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; -i&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; Microsoft.AspNetCore.Blazor.Templates::3.2.0-preview1.20073.1&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; LeagueManager&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; blazorwasm&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; LeagueManager&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first install’s the latest Blazor Web Assembly project template (at the time of writing, it’s 3.2.0 Preview 1). The second command creates a new project.&lt;/p&gt;
&lt;p&gt;Following the two commands with the below, gets the sample app up and running.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; .&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;\L&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;eagueManager&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;dotnet &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/i/4sunpxfj3xuck6ixv77v.PNG&quot; alt=&quot;Alt Text&quot;&gt;&lt;/p&gt;
&lt;p&gt;Out of the box, Blazor applications use Bootstrap and are created with some great examples of the key functionality (namely two-way model binding and making external requests).&lt;/p&gt;
&lt;p&gt;First things first, let’s add our own color scheme and font. I’ll also remove a lot of the standard Blazor code leaving a much more basic project structure.&lt;/p&gt;
&lt;p&gt;I’m also going to apply one of the principles I learned from React, which is to keep stateful components to an absolute minimum and make the majority of the application dumb.&lt;/p&gt;
&lt;p&gt;For that, I’m going to add two additional folders on top of the pre-configured ‘Pages’ folder with two new folders:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Components - Dumb, layout components&lt;/li&gt;
&lt;li&gt;Services - Stateful components&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Initially, I considered disposing of the Pages folder as well. But keeping actual pages (with routes) in one place seemed more logical.&lt;/p&gt;
&lt;p&gt;For this initial piece of front end of development, I need to be able to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View a list of teams&lt;/li&gt;
&lt;li&gt;Create a new team&lt;/li&gt;
&lt;li&gt;View details about a specific team&lt;/li&gt;
&lt;li&gt;Add players to a team&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In my head, that gives me two pages.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A list of all teams and the ability to create a new team&lt;/li&gt;
&lt;li&gt;A page to view a specific team containing a list of the team’s players and corresponding data entry form for adding new players&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;handling-state&quot;&gt;Handling State&lt;/h2&gt;
&lt;p&gt;Before I get into much detail about the page structure, I first wanted to see how HTTP data access works in Blazor.&lt;/p&gt;
&lt;p&gt;Turns out, the answer is extremely simple.&lt;/p&gt;
&lt;p&gt;The answer is a &lt;em&gt;huge +1&lt;/em&gt; already for using Blazor as a front end framework. The code written to manage to retrieve data from an external HTTP service is almost identical to code that would run in any kind of .NET application.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Collections&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Generic&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Net&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Http&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Text&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Text&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Json&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Threading&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Tasks&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; LeagueManager&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Models&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Microsoft&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;AspNetCore&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Components&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Microsoft&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Extensions&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Logging&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; LeagueManager&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Services&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; TeamState&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; LastSearch&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; IReadOnlyList&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Team&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; TeamSearchResults { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; bool&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; SearchInProgress { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; event&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Action&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; OnChange;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; HttpClient&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; _httpClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; ILogger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamState&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; TeamState&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            HttpClient&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; httpClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            ILogger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamState&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_httpClient&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; httpClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; DeletePlayer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Player&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            try&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogInformation&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; - &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; - &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Position&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; httpContent&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;StringContent&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;JsonSerializer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Serialize&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Encoding&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;UTF8&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; postResult&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_httpClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;DeleteAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;http://localhost:8080/team/&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;/players&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogInformation&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;postResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;StatusCode&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ToString&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;postResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IsSuccessStatusCode&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;                    NotifyStateChanged&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                    throw&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;postResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Content&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ReadAsStringAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            catch&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Message&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Failure adding player&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; AddPlayer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Player&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            try&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogInformation&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; - &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; - &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Position&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; httpContent&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;StringContent&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;JsonSerializer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Serialize&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Encoding&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;UTF8&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; postResult&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_httpClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;PostAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;http://localhost:8080/team/&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;/players&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;httpContent&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogInformation&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;postResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;StatusCode&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ToString&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;postResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IsSuccessStatusCode&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;                    NotifyStateChanged&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                    throw&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;postResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Content&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ReadAsStringAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            catch&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Message&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Failure adding player&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Team&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GetSpecific&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; teamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogInformation&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Running HTTP search&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; team&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_httpClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GetJsonAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamSearchResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;http://localhost:8080/team/&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;teamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; team&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Team&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; ReRunSearch&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Search&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;LastSearch&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Search&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; searchTerm&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            try&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LastSearch&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; searchTerm&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogWarning&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Running search&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;SearchInProgress&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;                NotifyStateChanged&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; searchResult&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_httpClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GetJsonAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamSearchResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;http://localhost:8080/team?search=&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;searchTerm&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;IsNullOrEmpty&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;searchResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Err&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                    this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamSearchResults&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; searchResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Teams&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;SearchInProgress&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;                NotifyStateChanged&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            catch&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Message&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Failure running search&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; CreateTeam&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Team&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; team&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            try&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogInformation&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;team&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; httpContent&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;StringContent&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;JsonSerializer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Serialize&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;team&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Encoding&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;UTF8&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; postResult&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_httpClient&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;PostAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;http://localhost:8080/team&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;httpContent&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogInformation&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;postResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;StatusCode&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ToString&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;postResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IsSuccessStatusCode&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;                    NotifyStateChanged&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                    throw&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;postResult&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Content&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ReadAsStringAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            catch&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ex&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Message&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_logger&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;LogError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Failure adding team&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; NotifyStateChanged&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;() =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OnChange&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;?.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Invoke&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A reasonably straightforward class that uses Dependency Injection to add a HttpClient and an ILogger. From there, it is mostly just a set of different methods handling the various different CRUD operations.&lt;/p&gt;
&lt;p&gt;** Note the terrible hardcoded URL, this is a work in progress :) **&lt;/p&gt;
&lt;p&gt;There are a couple of front-end/Blazor specific parts that I do just want to point out, however.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; IReadOnlyList&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Team&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; TeamSearchResults&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; bool&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; SearchInProgress&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; event&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Action&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; OnChange&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These three properties are all relevant to HTTP in Blazor.&lt;/p&gt;
&lt;p&gt;The Blazor application runs completely in a web browser. Therefore this TeamState object is specific to the client accessing the site.&lt;/p&gt;
&lt;p&gt;Therefore, whenever search runs we can hold a copy of the returned data in a property for easy retrieval if the search needs to happen again.&lt;/p&gt;
&lt;p&gt;SearchInProcess holds a value indicating that the search method is running. Imagine a front end in which a loading bar appears during a search, that could be bound to this property.&lt;/p&gt;
&lt;p&gt;The OnChange property is probably the most important of the three. It’s linked directly to this line of code here:&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; NotifyStateChanged&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;() =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OnChange&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;?.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Invoke&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, the OnChange property can be subscribed to by an external method. NotifyStateChanged then invokes that external method.&lt;/p&gt;
&lt;p&gt;Let’s dive into a real example. Here is the code for the Team List page.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@page&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;/teams&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; LeagueManager&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Services&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; LeagueManager&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Components&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Teams&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@inject&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; TeamState&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; state&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;team-search&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;new-team&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;CreateTeam&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; OnSave&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;this.CreateTeam&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;search-area&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Search&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; OnSearch&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;state.Search&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;search-results&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;SearchResults&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Teams&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;state.TeamSearchResults&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@code&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    protected&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; override&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; OnInitializedAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;        state&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OnChange&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; +=&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; StateHasChanged&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Search&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Empty&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; CreateTeam&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Team&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; team&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;CreateTeam&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;team&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ReRunSearch&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An instance of the TeamState object is injected into the page, and on PageLoad &lt;em&gt;(OnInitializedAsync is Blazor’s PageLoad event)&lt;/em&gt; the state Blazor page StateHasChanged event is subscribed to the OnChange event of the state injected state class.&lt;/p&gt;
&lt;p&gt;So, when a search runs within the TeamState object the OnChange event is triggered. In this instance, the StateHasChanged event of the Blazor page will execute. Taking wording straight from the &lt;a href=&quot;https://docs.microsoft.com/en-us/aspnet/core/blazor/lifecycle?view=aspnetcore-3.1#state-changes&quot;&gt;Microsoft docs&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“StateHasChanged notifies the component that its state has changed. When applicable, calling StateHasChanged causes the component to be rerendered.”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Binding any page to the OnChange event of the state will, therefore, cause the page to be re-rendered whenever our state components notify that something has changed. Cool!&lt;/p&gt;
&lt;h1 id=&quot;model-binding&quot;&gt;Model Binding&lt;/h1&gt;
&lt;p&gt;Now that we can retrieve data from the server and give that to the front end, it’d be fantastic to actually get it to display on the page.&lt;/p&gt;
&lt;h2 id=&quot;displaying-data&quot;&gt;Displaying data&lt;/h2&gt;
&lt;p&gt;Sticking with the best front end practices I’ve taken from JS, my Teams.razor page handles all of the state management. It then passes the data down to components to manage the display.&lt;/p&gt;
&lt;p&gt;A good example of this is the SearchResults component.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;col&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;row py-1&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;        @if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Teams&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Teams&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Count&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;No&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; results&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; found&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;table&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;table&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;thead&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;th&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; scope&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;col&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;th&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;th&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; scope&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;col&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;th&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;thead&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;tbody&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;                    @foreach&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Team&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; team&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Teams&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; @key&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;team.Id&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;th&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; scope&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;row&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                                &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; href&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;/teams/@team.Id&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;@team&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Id&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                            &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;th&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;td&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;@team&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;td&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;tbody&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;            &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;table&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Parameter&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; IReadOnlyList&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Team&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Teams&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above snippet raises one of the key parts of Blazor functionality. That being, the Parameter attribute.&lt;/p&gt;
&lt;p&gt;The parameter attribute indicates that a value can be passed into the component by way of an HTML element.&lt;/p&gt;
&lt;p&gt;In this case, there is a parameter that holds a list of Team objects.&lt;/p&gt;
&lt;p&gt;This component can certainly be classified as dumb.&lt;/p&gt;
&lt;p&gt;It takes a list of objects and either shows ‘no results found’, or creates an HTML table and loops through each Team object to create the table rows.&lt;/p&gt;
&lt;p&gt;C#. In the browser. It’s a magical time to be a .NET developer.&lt;/p&gt;
&lt;h2 id=&quot;creating-a-new-record&quot;&gt;Creating a new record&lt;/h2&gt;
&lt;p&gt;The final piece of this front end puzzle is creating new records.&lt;/p&gt;
&lt;p&gt;My absolute favourite feature of both Angular and React is the ability to be able to initialize a new instance of an object and bind that straight to an input in the HTML.&lt;/p&gt;
&lt;p&gt;Luckily, Blazor has taken notes from the JS big boys and offers a similar kind of function.&lt;/p&gt;
&lt;p&gt;For that, let’s have a look at the CreatePlayer component.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;EditForm&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Model&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@newPlayer&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;col&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;input-group mb-3&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;input&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;form-control&quot;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; placeholder&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; aria&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;label&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Search Term&quot;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; @bind&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;newPlayer.Name&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;input-group mb-3&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;InputSelect&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; @bind&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Value&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;newPlayer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Position&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;custom-select&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;option&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;GK&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Goalkeeper&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;option&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;option&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;DEF&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Defender&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;option&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;option&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;MID&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Midfielder&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;option&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;option&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;ST&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Striker&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;option&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;            &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;InputSelect&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;row py-1&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;ml-auto&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; @onclick&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;() =&amp;gt; OnSave.InvokeAsync(newPlayer)&quot;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;btn btn-danger px-5&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;                    Add&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; +&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;                &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;            &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;EditForm&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Parameter&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; EventCallback&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Player&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; OnSave&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Parameter&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; TeamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Player&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; newPlayer&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Player&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    protected&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; override&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; OnInitializedAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;        newPlayer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamId&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; base&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;OnInitializedAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the page is loaded, a new Player object is created. OnInitialization, the TeamId of the newly created player object is assigned from an input value.&lt;/p&gt;
&lt;p&gt;A TeamId is a requirement for a player object, so it probably makes sense to implement some kind of null check on the TeamId property just in case. But that’s a job for another day.&lt;/p&gt;
&lt;p&gt;From there, an EditForm component is added to the HTML. An EditForm parses out to a standard HTML form. However, it enables model binding between the DOM and the C# object.&lt;/p&gt;
&lt;p&gt;Using the @bind element, the HTML becomes reasonably straightforward. An input is bound to the player name property and a select dropdown is bound to the position property.&lt;/p&gt;
&lt;p&gt;When the form is submitted, the OnSave event callback is invoked.&lt;/p&gt;
&lt;p&gt;What the hell is an EventCallback?&lt;/p&gt;
&lt;p&gt;For that to make a little more sense, let’s take a quick look at a component that consumes this CreatePlayer component.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TeamMetadata.razor&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;@if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;TeamData&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Loading&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;@TeamData&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;h2&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Current&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Players&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;h2&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreatePlayer&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; OnSave&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;OnAddPlayer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; TeamId&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;@TeamId&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;PlayerList&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Players&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;@TeamData.Players&quot;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; OnDelete&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;OnDeletePlayer&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@code&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Parameter&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Team&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; TeamData&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Parameter&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; TeamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Parameter&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; EventCallback&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Player&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; OnAddPlayer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Parameter&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; EventCallback&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Player&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; OnDeletePlayer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;ViewTeam.razor&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@page&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; &quot;/teams/{TeamId}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Microsoft&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Extensions&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Logging&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; LeagueManager&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Components&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Teams&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@inject&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; TeamState&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; state&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamMetadata&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; TeamData&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;@teamData&quot;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; TeamId&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;@TeamId&quot;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; OnAddPlayer&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;state.AddPlayer&quot;&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; OnDeletePlayer&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;state.DeletePlayer&quot;&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;@code&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;Parameter&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; TeamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Team&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; teamData&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    protected&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; override&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; OnInitializedAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;        state&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;OnChange&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; +=&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; StateHasChanged&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        teamData&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GetSpecific&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ConfigureAwait&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;    protected&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; override&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; Task&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; OnAfterRenderAsync&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;bool&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; firstRender&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;        teamData&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; await &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GetSpecific&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;TeamId&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ConfigureAwait&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The two code snippets above are for the View Team page, and the corresponding TeamMetadata component within it.&lt;/p&gt;
&lt;p&gt;Sticking with the practice of having as little components managing state as possible, the ViewTeam page holds all the logic for loading the players and the creation of a new player.&lt;/p&gt;
&lt;p&gt;The state.AddPlayer method is passed down into the OnAddPlayer parameter of the TeamMetadata component, and from there into the OnSave parameter of the CreatePlayer component.&lt;/p&gt;
&lt;p&gt;So when the save button is clicked in the CreatePlayer component that event bubbles all the way up to state.AddPlayer method. The newly created and data-bound Player object goes along for the ride and is sent off to our backend server for creation.&lt;/p&gt;
&lt;p&gt;I will say it again…&lt;/p&gt;
&lt;p&gt;C#. In the browser. It’s a magical time to be a .NET developer.&lt;/p&gt;
&lt;h1 id=&quot;in-summary&quot;&gt;In Summary&lt;/h1&gt;
&lt;p&gt;Sometimes I can waffle a little bit with these summary sections. This time, not so much.&lt;/p&gt;
&lt;p&gt;Blazor is one of the best web technologies I have ever worked with. I’m probably biased, being a .NET developer. But I no longer need to stumble my way through the world of Javascript.&lt;/p&gt;
&lt;p&gt;And that my friends is a magical place to be.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item><item><title>Clean Architecture in .NET Core</title><link>https://blog.jameseastham.co.uk/blog/clean-architecture-dotnet-core/</link><guid isPermaLink="true">https://blog.jameseastham.co.uk/blog/clean-architecture-dotnet-core/</guid><description>Clean Architecture is a way of designing and building software first proposed by Uncle Bob Martin in his book of the same name. In this post, we take a look at applying clean architecture principles in .NET Core.</description><pubDate>Wed, 15 Jan 2020 21:13:01 GMT</pubDate><content:encoded>&lt;p&gt;I recently wrote an article around the importance of automating the coding standards around your codebase.&lt;/p&gt;
&lt;p&gt;Whether that be tabs vs spaces, the number of classes per file or the way comments are structured. It makes the legibility of code so much better when there is a standard and common theme.&lt;/p&gt;
&lt;p&gt;The standard repo I use can be found &lt;a href=&quot;https://github.com/jeastham1993/standard-repo&quot;&gt;here&lt;/a&gt;. I’ve now gone a step further with these standards and added my understanding of the Clean Architecture principles.&lt;/p&gt;
&lt;h1 id=&quot;clean-architecture&quot;&gt;Clean Architecture&lt;/h1&gt;
&lt;p&gt;Clean Architecture is a way of designing and building software first proposed by Uncle Bob Martin in his book of the same name.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://thepracticaldev.s3.amazonaws.com/i/34fsbx5oopko835yl8bj.jpg&quot; alt=&quot;Alt Text&quot;&gt;&lt;/p&gt;
&lt;p&gt;This image has been repeated many times around the web (all credit to Uncle Bob) but it really clearly defines the way an application should be designed.&lt;/p&gt;
&lt;p&gt;Each circle should only know anything about the circles within, no dependencies should extend outwards.&lt;/p&gt;
&lt;p&gt;So what does that mean for our software? &lt;em&gt;All the following examples can be found in my GitHub repo&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;entities&quot;&gt;Entities&lt;/h2&gt;
&lt;p&gt;Entities are the purest representation of a business domain. In my example application for managing loans for a local bank, the entities are as follows.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Collections&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Generic&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Text&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Entities&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Exceptions&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Core&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Entities&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// Encapsulates all code for managing loans.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; abstract&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Loan&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Initializes a new instance of the &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;Loan&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt; class.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;principal&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The principal valie of the loan.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;rate&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The annual interest rate percentage.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;period&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The term of the loan.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        internal&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Loan&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; principal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; rate&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; period&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Principal&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; principal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Rate&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; rate&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Period&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; period&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Balance&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; principal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the standard late fee to be charged.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; virtual&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; LateFee&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            get&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                return&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 125M&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the initial principal of the loan.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Principal { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the interest rate of the loan.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Rate { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the period the loan will be repayed over.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Period { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the current balance of the loan.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Balance { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Make a payment against the loan.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;paymentAmount&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The value of the payment made.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; virtual&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; MakePayment&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; paymentAmount&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; newCalculatedBalance&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Balance&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; paymentAmount&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;newCalculatedBalance&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                throw&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LoanOverpaymentException&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;A payment of &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;paymentAmount&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; would take the current loan balance below 0&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Balance&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Balance&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; paymentAmount&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Apply the interest for the elapsed period.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;returns&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The total accrued interest value.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;returns&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; virtual&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; ApplyInterest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Balance&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Principal&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Rate&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Balance&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Principal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Charge a late payment fee to this loan.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;returns&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The new balance after the late fee has been added.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;returns&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; virtual&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; ChargeLateFee&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Balance&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Balance&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;LateFee&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Balance&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A loan is the most fundamental entity that the bank department works with. Within each loan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A payment can be made off the balance&lt;/li&gt;
&lt;li&gt;Interest can be applied&lt;/li&gt;
&lt;li&gt;A late fee can be charged&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Following the Open/Closed Principle, the class is created as abstract to allow different types of loans to be created. An example can be seen in the concrete BasicLoan class&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Collections&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Generic&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Text&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Core&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Entities&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// A basic loan implementation.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; BasicLoan&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Loan&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        internal&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; BasicLoan&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; principal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; rate&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; term&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            : &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;base&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;principal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;rate&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;term&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A basic loan doesn’t override any of the base Loan functionality but in the future, it may well be extended.&lt;/p&gt;
&lt;p&gt;The bank also has Customers. Again these are represented in a way that is as aligned as possible to the actual business use case. Using the same terminology as the business uses for the entities makes communication between developers and domain experts extremely easy.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Collections&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Generic&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Runtime&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CompilerServices&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Text&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;assembly&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;InternalsVisibleTo&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;CleanArchitecture.UnitTest&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Core&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Entities&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// Encapsulates all logic for a customer entity.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Customer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; _age&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Initializes a new instance of the &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;Customer&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt; class.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The new customers name.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;address&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The new customers address.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;dateOfBirth&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The new customers date of birth.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;nationalInsuranceNumber&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The new customers national insurance number.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        internal&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Customer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; address&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DateTime&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; dateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; nationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CustomerId&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Guid&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;NewGuid&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ToString&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Address&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; address&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; dateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;NationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; nationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        private&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Customer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the internal identifier of this customer.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; CustomerId { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the name of the customer.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Name { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the address of the customer.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Address { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the customers date of birth.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; DateTime&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; DateOfBirth { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the national insurance number of the customer.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; NationalInsuranceNumber { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the customers credit score.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; CreditScore { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the age of the person based on their &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;Customer.DateOfBirth&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Age&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            get&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_age&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; &amp;lt;=&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                    this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_age&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DateTime&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DateTime&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Now&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Subtract&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Ticks&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Year&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                return&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_age&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        internal&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; UpdateCreditScore&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;decimal&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; newCreditScore&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;newCreditScore&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreditScore&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreditScore&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; newCreditScore&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Within the Entities ‘circle’ I also hold the interface that allows interactions with the customer database.&lt;/p&gt;
&lt;p&gt;One of the biggest takeaways from Clean Architecture is to keep the business logic and use cases as far away from the details (dB provider, user interactions) as possible.&lt;/p&gt;
&lt;p&gt;It’s for this reason, the Entities have a concept of a ICustomers datastore but no actual understanding or care about how the Customers datastore actually works.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// ------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Copyright (c) James Eastham.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// ------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Collections&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Generic&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Text&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Threading&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Tasks&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Core&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Entities&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// Encapsulates all persistance of customer records.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; interface&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; ICustomerDatabase&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Store the customer object in the database.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;customer&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;Customer&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt; to be stored.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Store&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Customer&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; customer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once we have the Entities mapped out, we can then move on to the next circle outwards.&lt;/p&gt;
&lt;h2 id=&quot;use-cases&quot;&gt;Use Cases&lt;/h2&gt;
&lt;p&gt;Use cases hold an actual business use of the application. If the entities hold the core business objects, the use cases hold the logic on how these objects work together.&lt;/p&gt;
&lt;p&gt;Uncle Bob puts it quite nicely (paraphrasing here)&lt;/p&gt;
&lt;p&gt;“Using a bank as an example. The calculation of the interest on a loan would come under an entity, as that is a rule that is fundamental to the business. It is a critical business rule.&lt;/p&gt;
&lt;p&gt;However, a system that determines if a specific customer should be allowed to take out a loan or not is something that would benefit from being automated. That is a use case. A use case is a description of the way an automated system is used, it specifies the inputs to be provided by the user and the outputs returned to the user.”&lt;/p&gt;
&lt;p&gt;Keeping that exact sample in mind, let’s add a use case for checking to see if a customer can take out a loan.&lt;/p&gt;
&lt;p&gt;First, we will look at the expected inputs and outputs.&lt;/p&gt;
&lt;p&gt;From the conversation we had with a domain expert at the bank, we know there are some key decisions that govern if a loan is accepted or not.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The customer must have a valid name, address and National Insurance number&lt;/li&gt;
&lt;li&gt;They must be older than 18&lt;/li&gt;
&lt;li&gt;They must have a credit score greater than 500&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Translating that logic into request/response objects.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// ------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Copyright (c) James Eastham.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// ------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Core&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// Gather required data for a new loan.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    protected&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; GatherContactInfoRequest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        : &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;GatherContactInfoResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Initializes a new instance of the &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;GatherContactInfoRequest&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt; class.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The applicants name.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;address&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The applicants address.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;dateOfBirth&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The applicants date of birth.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;nationalInsuranceNumber&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;The applicants NI number.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; GatherContactInfoRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; address&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DateTime&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; dateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; nationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Address&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; address&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; dateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;NationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; nationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the name.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Name { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the address.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Address { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the date of birth.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; DateTime&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; DateOfBirth { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets the National Insurance number.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; NationalInsuranceNumber { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// ------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Copyright (c) James Eastham.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// ------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Collections&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Generic&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Core&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// Response from a successul gather of ContractInfo.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    protected&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; GatherContactInfoResponse&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        : &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;BaseResponse&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        internal&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; GatherContactInfoResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; address&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DateTime&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; dateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; nationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            : &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;base&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Address&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; address&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; dateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;NationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; nationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets or sets the applicants name.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Name { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets or sets the applicants address.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; Address { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets or sets the applicants date of birth.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; DateTime&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; DateOfBirth { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets or sets the applicants national insurance number.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; NationalInsuranceNumber { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets or sets the applicants credit score.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; decimal&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; CreditScore { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Gets a value indicating if the customer has been accepted for a loan.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; bool&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; IsAcceptedForLoan  { &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We end up with the two above classes. Name, address, date of birth and NI number go in. A credit score and ‘IsAcceptedForLoan’ comes out.&lt;/p&gt;
&lt;p&gt;Keeping the request and response in mind, and using the recommened best Clean Architecture practice, we can create a GatherContactInfoInteractor.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// ------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Copyright (c) James Eastham.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// ------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Threading&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Tasks&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Core&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Entities&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Core&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Services&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Core&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// Handles a &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;GatherContactInfoRequest&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; GatherContactInfoInteractor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        : &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IRequestHandler&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;GatherContactInfoRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;GatherContactInfoResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; ICreditScoreService&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; _creditScoreService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        private&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; ICustomerDatabase&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; _customerDatabase&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Initializes a new instance of the &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;GatherContactInfoInteractor&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt; class.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;creditScoreService&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;A &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;ICreditScoreService&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;customerDatabase&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;A &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;ICustomerDatabase&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; GatherContactInfoInteractor&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ICreditScoreService&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; creditScoreService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ICustomerDatabase&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; customerDatabase&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_creditScoreService&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; creditScoreService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_customerDatabase&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; customerDatabase&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Handle the given &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;GatherContactInfoRequest&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;request&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;A &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;GatherContactInfoRequest&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;returns&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;A &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;see&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; cref&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;GatherContactInfoResponse&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;returns&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; GatherContactInfoResponse&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Handle&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;GatherContactInfoRequest&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; is &lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                throw&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ArgumentNullException&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(nameof(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; response&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;GatherContactInfoResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Address&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;NationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;IsNullOrEmpty&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                response&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Name cannot be empty&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;IsNullOrEmpty&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Address&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                response&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Address cannot be empty&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;IsNullOrEmpty&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;NationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                response&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;National Insurance number cannot be empty.&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; customerRecord&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Customer&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Address&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;DateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;NationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;customerRecord&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Age&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 18&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                response&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;A customer must be over the age of 18&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;response&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;HasError&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                response&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreditScore&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_creditScoreService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;GetCreditScore&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;NationalInsuranceNumber&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;response&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreditScore&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; 500&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                    this&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;_customerDatabase&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Store&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;customerRecord&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                    response&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;AddError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Credit score is too low, sorry!&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; response&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’m not going to talk through the code line by line, but you can see that the business use case is clear and explicit.&lt;/p&gt;
&lt;p&gt;A new developer coming into the look at this class can see with reasonably little difficulty what is going on. It’s clear and concise and very close to the actual business domain.&lt;/p&gt;
&lt;p&gt;It’s also not a huge stretch to imagine sitting down with a non-programmer and being able to talk through this code file line by line to iron out any issues.&lt;/p&gt;
&lt;p&gt;So now we have the core of our business mapped (it’s a very small bank), but how do we actually use the code.&lt;/p&gt;
&lt;h2 id=&quot;ui&quot;&gt;UI&lt;/h2&gt;
&lt;p&gt;Now we have the business logic worked out, we can start to think about how people at the bank can actually interact with the software.&lt;/p&gt;
&lt;p&gt;In this case, the bank are more than happy having a small executable they can run, key in the information manually and wait for a result to come back.&lt;/p&gt;
&lt;p&gt;Because all of our business logic is contained in our core library, the console app becomes really simple.&lt;/p&gt;
&lt;pre class=&quot;astro-code one-dark-pro&quot; style=&quot;background-color:#282c34;color:#abb2bf; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// ------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// Copyright (c) James Eastham.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;// ------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Core&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Requests&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; CleanArchitecture&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ConsoleApp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// Main application entry point.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;    /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; static&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Program&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// Main application entry point.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;        /// &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#D19A66;font-style:italic&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#98C379;font-style:italic&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7F848E;font-style:italic&quot;&gt;Arguments passed into the application at runtime.&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#E06C75;font-style:italic&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF;font-style:italic&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;        public&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; static&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt; Main&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;[] &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#D19A66&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                throw&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;ArgumentException&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;args cannot be null&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; getContactInteractor&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;GatherContactInfoInteractor&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;MockCreditScoreService&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(), new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CustomerDatabaseInMemoryImpl&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Name?&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ReadLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Address?&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; address&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ReadLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Date of birth (yyyy-MM-dd)?&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; dateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; DateTime&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Parse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ReadLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;NI Number?&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; niNumber&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ReadLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; getContactResponse&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; getContactInteractor&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;Handle&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;GatherContactInfoRequest&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;address&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;dateOfBirth&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;niNumber&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;getContactResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;HasError&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                foreach&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; error&lt;/span&gt;&lt;span style=&quot;color:#C678DD&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; getContactResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;Errors&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                    Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;            else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C678DD&quot;&gt;                var&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt; result&lt;/span&gt;&lt;span style=&quot;color:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt; getContactResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;IsAcceptedForLoan&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; ? &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;accepted&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;rejected&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;                Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;$&quot;Credit score is &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;getContactResponse&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;CreditScore&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt; so customer has been &lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E06C75&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#98C379&quot;&gt;&quot;Press any key to close&quot;&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E5C07B&quot;&gt;            Console&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#61AFEF&quot;&gt;ReadKey&lt;/span&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The UI is only concerned with how the data is presented to the user, it has no concern over how a customer gets validated.&lt;/p&gt;
&lt;p&gt;If in 6 months the bank decides they want to allow potential customers to validate themselves through a website instead of manual entry the process is nice and simple.&lt;/p&gt;
&lt;p&gt;The EXACT same library can be used, how that interface is served up is completely irrelevant.&lt;/p&gt;
&lt;p&gt;Suddenly, this bank can be a lot more agile to changes outside of their control.&lt;/p&gt;
&lt;p&gt;If a new technological trend kicks off and banks start identifying potential customers behind their backs (banks haven’t heard of GDPR you see) they can again use the EXACT same library to run the validation.&lt;/p&gt;
&lt;p&gt;It’s also at runtime that the implementations of the CreditScoreService and the CustomersDatabase are injected.&lt;/p&gt;
&lt;h1 id=&quot;summary&quot;&gt;Summary&lt;/h1&gt;
&lt;p&gt;I’ve seen a lot of posts and comments around Clean Architecture stating it can be overkill for a lot of projects.&lt;/p&gt;
&lt;p&gt;I do agree with this statement for small utility applications or any ‘one-off’ programs that will be used for a hotfix of any kind. However, I believe any applications that will be used in any kind of production scenario should be built in the right way from the ground up.&lt;/p&gt;
&lt;p&gt;Small choices, like decoupling the database from the business logic, make the application so much more resilient to change.&lt;/p&gt;
</content:encoded><dc:creator>James Eastham</dc:creator></item></channel></rss>