今日已更新 240 条资讯 | 累计 23823 条内容
关于我们

标签:#designpatterns

找到 4 篇相关文章

AI 资讯

SOLID Design Principles: Stop Writing Code That Breaks When You Touch It

Guidelines, not rules. Here's the difference — and why it matters. What is SOLID? SOLID is a set of software design guidelines — not hard rules, but principles that guide how we organize our code. The goal is simple: as your codebase grows and your team scales, things should get easier to change, not harder. SOLID is what makes that possible. Five principles. One goal. Let's walk through each one with real code. S — Single Responsibility Principle A class, function, or method should have one and only one reason to change. The Violation class Bird : def __init__ ( self , name : str , bird_type : str ): self . name = name self . bird_type = bird_type def make_sound ( self ): # two jobs — deciding the type AND making the sound if self . bird_type == " parrot " : print ( " Squawk! " ) elif self . bird_type == " eagle " : print ( " Screech! " ) elif self . bird_type == " owl " : print ( " Hoot! " ) else : print ( " ... " ) make_sound() has two responsibilities — deciding which bird type it is AND making the sound. That's two reasons to change. Add a new bird? Touch make_sound() . Change how sounds work? Touch make_sound() again. Two different reasons, one method. SRP violated. The Fix from abc import ABC , abstractmethod class Bird ( ABC ): def __init__ ( self , name : str ): self . name = name @abstractmethod def make_sound ( self ): pass class Parrot ( Bird ): def make_sound ( self ): print ( " Squawk! " ) class Eagle ( Bird ): def make_sound ( self ): print ( " Screech! " ) class Owl ( Bird ): def make_sound ( self ): print ( " Hoot! " ) # Usage birds = [ Parrot ( " Polly " ), Eagle ( " Sam " ), Owl ( " Oliver " )] for bird in birds : bird . make_sound () Now each class has one responsibility. Parrot.make_sound() only changes if parrots change how they sound. Nothing else touches it. O — Open/Closed Principle A class should be open for extension but closed for modification. SRP and OCP go hand in hand. When you fixed SRP in the Bird example above — you also fixed OCP.

2026-07-22 原文 →
AI 资讯

Your Error Messages Are Written for Developers, Not Users

Open the network tab on almost any web app, trigger a failed request, and you'll usually find one of two things staring back at the user: a raw stack trace, or a message so generic it might as well say "something happened." Neither one helps. Both exist for the same reason they were written by developers, for developers, and never translated for the person actually using the product. The Error Message Nobody Designed Most UI elements go through some level of design scrutiny. Buttons get spacing decisions. Forms get validation states. But error messages? They're usually whatever string got thrown at the moment something broke, copy-pasted straight from a try/catch block into a toast notification. "Error 500: Internal Server Error." "Failed to fetch." "Unexpected token in JSON at position 4." These are diagnostic breadcrumbs for engineers debugging a system. To a user trying to submit a form or complete a purchase, they're just noise confirmation that something went wrong, with zero indication of what to do next. This is where good web app design services earn their keep not in the buttons and layouts everyone notices, but in the failure states nobody plans for until users start complaining. Why This Keeps Happening It's not that teams don't care. It's that error handling sits at the intersection of two disciplines that rarely talk to each other at the moment. Backend logic throws whatever exception the code produces. The front end just needs something to display so the app doesn't silently freeze. Nobody's job, at that moment, is to ask: "what should the user actually understand right now?" The result is a UI layer that's polished everywhere except the one place users encounter when things go wrong which, ironically, is exactly when clear communication matters most. What a Good Error Message Actually Does A well-designed error message does three things a raw exception never does. It tells the user what happened, in plain language not "Error: NetworkException," but "W

2026-07-21 原文 →
开发者

Making ServiceLoader usable: a provider factory

I keep coming back to java.util.ServiceLoader . I have used it to put a JSON layer behind a contract, so the core code carries no direct dependency on any particular JSON library and I can swap the implementation without touching callers. The same shape works for JWT handling, where the concrete library might be jose4j or another JOSE implementation, and you can easily find other decoupling use-cases. The motivation is always the same: the application should depend on a capability, not on a vendor. A while back I wrote about exactly that idea in Rediscovering Java ServiceLoader: Beyond Plugins and Into Capabilities , where the argument was to treat ServiceLoader as capability discovery rather than a plugin system. That piece hit the limitation everyone hits — the no-argument constructor — and worked around it with a default constructor plus a dynamic proxy that built the real object through a factory on each call. It works, but it is indirection bolted on after the fact, not a design. This post is the part I never pinned down back then: turning that workaround into a small, explicit pattern. The running example below is a mock payments system, with Stripe and PayPal specializations, because it is compact enough to show end to end. The JSON and JWT cases cited can be built with the same structure. The two limits ServiceLoader leaves you The first is the no-argument constructor. Whatever ServiceLoader instantiates must have a public, parameterless constructor. My StripePaymentService takes an API key, so it cannot be the class ServiceLoader loads — not unless I bolt on some init-after-construction step, which I would rather avoid. The second is selection, or rather the lack of it. ServiceLoader gives you every implementation it finds, in roughly classpath order. There is no id, nothing to prioritise on, and no way to ask whether a given one even applies in the current environment. With two backends on the classpath and only one configured, working out which to use is

2026-07-14 原文 →
AI 资讯

Enterprise Design Patterns in Python: Repository & Unit of Work — Real-World E-Commerce Example

Enterprise Design Patterns in Python: Repository & Unit of Work 🐍🏗️ Series: Enterprise Application Architecture | Source: Fowler's EAA Catalog | Code: GitHub Repository 🧠 What Are Enterprise Design Patterns? Martin Fowler's Patterns of Enterprise Application Architecture (2002) is one of the most influential books in software engineering. It documents recurring architectural solutions — patterns — that solve common problems in enterprise systems: how to organize domain logic, how to talk to databases, how to handle transactions, and more. In this article, we'll explore two of the most powerful and widely-used patterns from that catalog: Pattern Category Core Purpose Repository Data Source Abstracts data access behind a collection-like interface Unit of Work Data Source Tracks object changes and commits them as a single transaction These two patterns work beautifully together — and you'll see exactly why with a real-world example. 🛒 The Problem: An E-Commerce Order System Imagine you're building a backend for an online store. When a customer places an order: A new Order is created Each Product 's stock is decremented A Payment record is registered If any of these steps fail midway, the entire operation should roll back — no partial state. This is exactly the problem the Unit of Work pattern solves, and the Repository pattern makes it all cleanly testable. 📁 Repository Pattern Definition "A Repository mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects." — Martin Fowler, PoEAA The Repository acts as an in-memory collection of domain objects. Your business logic never knows if it's talking to PostgreSQL, SQLite, or even a mock list — it just calls .add() , .get() , .list() . Domain Model # models.py from dataclasses import dataclass , field from typing import List from uuid import uuid4 @dataclass class Product : id : str name : str price : float stock : int @dataclass class OrderItem : product_id : str qua

2026-06-20 原文 →