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

标签:#webdev

找到 2678 篇相关文章

AI 资讯

New HTTP QUERY Method (RFC 10008) Explained | Stop Using POST for Search

Introduction In June 2026, the IETF published RFC 10008 - the first new general-purpose HTTP method since PATCH was introduced in 2010. The method is called QUERY . In simple terms: QUERY = Safety of GET + Body of POST You can now send complex search/filter queries in the request body, while the server knows the operation is safe and idempotent . This means caching, automatic retries, and CDNs can all work properly. This single change can finally end the long-standing practice of using POST for search. The Problem We Had 1. Limitations of GET With GET, query parameters go in the URL: GET /products?category=electronics&price_min=1000&price_max=50000&brand=samsung,apple&sort=-rating&page=1&limit=20 When filters become complex (JSON filters, nested conditions, many tags), the URL easily exceeds 8,000 characters. Many servers, proxies, and browsers struggle with this. URLs also get logged, bookmarked, and shared — which is often undesirable. 2. Problems with POST So many developers started using POST for search: POST /products/search Content-Type: application/json { "filters": { "category": "electronics", "price": { "min": 1000, "max": 50000 }, "brands": ["samsung", "apple"] }, "sort": "-rating", "page": 1, "limit": 20 } But POST is not safe and not idempotent . That means: Caches and CDNs cannot safely cache the response Automatic retries after network failures are risky The server may treat it as a state-changing operation We have been pretending that a read operation is a write operation for years. What is the QUERY Method? According to RFC 10008: A QUERY requests that the request target process the enclosed content in a safe and idempotent manner and then respond with the result of that processing. In plain English: You send the query in the request body (like POST) The server processes it and returns the result It does not change any server state (like GET) Sending the same request multiple times produces the same result (idempotent) Comparison Table Property GET Q

2026-08-05 原文 →
AI 资讯

CSS Challenges for 200 IQ

Do you ever get that feeling when you’re working on a task, hit a wall with some problem, and something inside you whispers that there has to be a solution? When it seems like all is lost, like you’ve run into a fundamental limit of reality, but your refusal to accept it keeps driving you deeper into spec docs, 10-year-old GitHub threads, and articles from giants who’ve already blazed this trail and shared their findings? And then, after hours of intense brain-grinding, you add that final line of code, refresh the page, and there it is — the exact result you wanted, staring back at you from the screen? That rush of success is probably familiar to every engineer in some form or another. In those moments, I always want to share the win with my colleagues and, if it could help others, write an article about it. In this post, I’ve collected 3 such cases from our work where we came up with solutions that, as far as I know, are pretty unique and haven’t been fully documented before. I invite you to share in the joy of discovering a solution that seemed impossible! Fixed inside a Scroll Container For a warm-up, let’s take an easier task. One of my most popular CodePens is an example of a fixed block inside a scrolling container. People find it via Stack Overflow answers, so it’s an in-demand problem, so it might come in handy for you too. I’ve been working on an Angular component library called Taiga UI for many years. Everything I’ll talk about in this article comes from there, but that’s just the backstory. We won’t need Angular or any of its specifics here. We’re talking pure CSS. Our library uses a custom scrollbar. While modern browsers let you tweak its appearance a bit , for full control over behavior and visuals, we need to place our own elements inside the container to act as the scrollbar. But how do you do that when absolutely positioned elements fly to the top on scroll, and fixed-position ones are pinned to the viewport? Experienced devs will immediately think

2026-08-05 原文 →
AI 资讯

Designing a Reliable PDF Translation Job Pipeline in TypeScript

Uploading a PDF and calling a translation model looks like a two-step feature. In production, it is a job pipeline with untrusted input, two different extraction paths, several expensive stages, and an output that can be fluent while still being wrong. That distinction matters for a small SaaS team. The translation request may come from support, sales, or an internal operations task. Nobody wants to operate a document platform, but the workflow still needs to answer basic questions: Was the upload actually a PDF? Does the file contain selectable text or scanned page images? Can a retry create a second charge or a conflicting result? What happens when page 37 fails after the first 36 pages succeed? How do we know the translated PDF is not blank or visually broken? When are the source and result deleted? The translation model is one component. Reliability comes from the system around it. Define the Job Contract First I would not let a file reach an extractor until the API has established a narrow contract. For example, a translation request might include: type TranslationStyle = " general " | " technical " | " academic " ; interface CreateTranslationJob { uploadId : string ; sourceLanguage : string | " auto " ; targetLanguage : string ; style : TranslationStyle ; idempotencyKey : string ; containsRestrictedData : boolean ; } The request should be rejected when the source and target languages are identical, the upload is missing, the target language is unsupported, or policy says the document cannot leave an approved environment. File validation should also be explicit. Do not trust the filename or browser-supplied MIME type. Check at least: the actual byte size; the file signature; whether the parser can open the document; whether the PDF is encrypted; the page count; whether the job fits the account or product limit. A 20 MB limit is simple to explain in a user interface, but size alone is not a good predictor of work. A compressed 200-page text PDF can be smaller th

2026-08-05 原文 →
AI 资讯

Building an Editable 3D Indoor Map in the Browser

Indoor maps are often treated as a rendering problem: take a floor plan, extrude a few walls, and display the result. That is useful for a viewer, but it breaks down when a team needs to edit a real space, place assets, or hand the result to another application. We are building KiMap around a different boundary: turn a floor plan into an editable indoor scene in the browser, then keep the resulting structure useful for an SDK consumer. Why a floor plan is not enough A production indoor workflow needs more than a textured image on a plane. At minimum, the editor has to preserve the relationships between walls, floors, rooms, openings, and the objects placed in the space. Those relationships determine whether the result can later support navigation, facility workflows, a digital twin, or a custom web experience. That is why the current KiMap workflow starts with structure. You can define the indoor geometry, inspect it in 2D and 3D, and keep editing instead of committing to a static export too early. The browser editor boundary The editor is built with React and Three.js. The goal is not to replace every DCC tool. It is to make the early spatial workflow accessible to teams that need to test an indoor experience before investing in a full custom pipeline. The parts we are concentrating on are: editable floor-plan structure and bounded spaces 2D and 3D scene inspection in the same workflow reusable 3D furniture and local asset handling saving an indoor project without dropping the referenced model data a path toward SDK-oriented rendering and integration The last point matters. A scene that looks correct in an editor is not automatically useful to an application. We want the data boundary to be explicit enough that an SDK consumer can load the geometry and assets without rebuilding the scene from scratch. What we are testing next KiMap is in free early access. The most useful feedback is not generic interest; it is a concrete blocker from someone building an indoor-nav

2026-08-05 原文 →
AI 资讯

Environment Variables the Safe Way

Environment Variables the Safe Way Environment variables are the standard way to configure applications without hardcoding secrets or environment-specific details. But they're easy to misuse. I've seen API keys committed to repos, configs that crash when a variable is missing, and defaults that silently override production settings. Here's how I handle them safely. Never Commit Secrets The most important rule: never put real secrets in your code or commit them to version control. That includes .env files. Add .env to your .gitignore immediately. If you're using a framework like Laravel or a tool like Vite, the default .env.example is your friend. Commit that, but never the real one. For local development, you can generate a .env from the example and fill in your own values. For production, set variables through your hosting provider's dashboard or a secrets manager like AWS Secrets Manager or HashiCorp Vault. Read Variables Explicitly Don't access process.env directly all over your codebase. Instead, centralize your configuration. Create a config.js (or config.ts ) that reads and validates all the variables you need. // config.js const required = [ ' DATABASE_URL ' , ' JWT_SECRET ' , ' PORT ' ]; const missing = required . filter ( key => ! process . env [ key ]); if ( missing . length ) { throw new Error ( `Missing required environment variables: ${ missing . join ( ' , ' )} ` ); } module . exports = { databaseUrl : process . env . DATABASE_URL , jwtSecret : process . env . JWT_SECRET , port : parseInt ( process . env . PORT , 10 ) || 3000 , }; Now your app imports config and uses config.port . This has several benefits: Fail fast: if a required variable is missing, the app crashes at startup, not later when you try to use it. Type safety: you can parse and validate values once. Easy to mock in tests. Use Defaults Carefully Defaults are convenient, but they can hide problems. For example, if you default PORT to 3000 in production, you might accidentally run on the w

2026-08-05 原文 →
AI 资讯

Liquid Glass on the Web: 6 Ways to Build It with CSS and SVG

Apple shipped Liquid Glass across iOS 26 and macOS, and suddenly every product I look at has a frosted panel floating over something. I spent a few weeks rebuilding the effect properly for a project, and most of what I found online stops at one line: backdrop-filter : blur ( 16 px ); Which gives you a gray rectangle. That's not what makes Apple's version look like glass, and figuring out the difference took me longer than it should have. So here are the six techniques I ended up with, roughly in order of how well they're supported, along with the things that wasted my time. 1. The plain glassmorphism card Everyone knows this one, but there are three parts to it and most implementations ship only the first. .glass-card { position : absolute ; inset : 20% ; border-radius : 16px ; backdrop-filter : blur ( 16px ) saturate ( 180% ); -webkit-backdrop-filter : blur ( 16px ) saturate ( 180% ); background-color : rgba ( 255 , 255 , 255 , 0.08 ); border : 1px solid rgba ( 255 , 255 , 255 , 0.12 ); box-shadow : 0 8px 32px rgba ( 0 , 0 , 0 , 0.2 ); pointer-events : none ; } The saturate(180%) is the part I kept forgetting, and it turns out to be the whole trick. Blurring averages colors together, and averaging colors drains saturation out of them — so a pure blur comes out looking like dirty plastic rather than glass. Pushing saturation back up compensates. Drag it down to 100% in the pen above and you'll see the effect just die. The background tint matters for a similar reason. With a fully transparent background you get a blur but no surface — nothing reads as a physical pane sitting there. Something around 8% white is enough to suggest one without washing out whatever is behind it. Wrapped in React, so the numbers are adjustable: " use client " ; type GlassCardProps = { blur ?: number ; saturate ?: number ; opacity ?: number ; radius ?: number ; }; export default function GlassCard ({ blur = 16 , saturate = 180 , opacity = 0.08 , radius = 16 , }: GlassCardProps ) { return (

2026-08-05 原文 →
AI 资讯

SEO, AEO, GEO: A Technical Breakdown for Developers Building for Search and AI Answers

I'm a brand strategist, not a developer — but every campaign I run eventually turns into a conversation with someone's engineering team. Over the past year, that conversation has shifted. It used to be about meta tags and sitemaps. Now it's about whether a site is even readable by the models powering AI answers. Here's the technical breakdown I actually walk dev teams through. SEO (Search Engine Optimization) This is the one most engineers already know. Crawlable HTML, clean URL structure, fast Core Web Vitals, valid schema.org markup, an accurate sitemap.xml and robots.txt. The mechanics haven't changed much — what's changed is how much weight structured data carries now, because it's the same markup that AEO and GEO systems lean on. AEO (Answer Engine Optimization) This is about formatting content so it can be lifted directly into a featured snippet or a voice/chat answer. Practically, that means: a direct, self-contained answer to the implied question within the first 1-2 sentences of a section, genuine FAQ schema ( FAQPage in JSON-LD, not just visually-styled accordions), and heading structure that maps to actual questions people ask, not just keyword strings. If a section can't be understood correctly when read on its own, out of context, it won't get picked up. GEO (Generative Engine Optimization) This is the newest layer, and it's aimed at large language models rather than traditional crawlers — think AI Overviews, Perplexity, ChatGPT's browsing mode. A few things I've seen actually move the needle here: an llms.txt file at the root (still informal, not a ratified standard, but increasingly respected), consistent factual claims about an entity across every page and every third-party mention (NAP consistency isn't just a local-SEO thing anymore, it's an entity-recognition thing), and content that states things plainly rather than burying them in marketing language — generative models tend to extract and cite the most unambiguous sentence in a block, so ambigui

2026-08-05 原文 →
AI 资讯

How I cut my Chromatic bill 10x (works on any visual testing tool)

I have been a huge Storybook and Chromatic fan for years. But at some point the bill got my attention, and when I looked into why, the fix turned out to be simple. This is the write-up of what I changed. It works on any per-snapshot tool, not just Chromatic. First, some backstory on how I got here, because it explains why the cost crept up in the first place. How I ended up paying for a lot of snapshots In the past I would build a gigantic end-to-end pipeline that was flaky as hell and made me spend time every week fixing it. It took 40 minutes to run, and when it went red someone would assume it was just flaky, merge the change anyway, and then find out it truly did break the system. So I stopped writing lots of E2Es and moved to Storybook for interaction and visual testing. Much better. But because I was rendering every state of every component as its own story to get the screenshots in place, I was generating a lot of screenshots. And every snapshot tool, Chromatic, Percy, Playwright screenshots, UI Verify, renders and bills per story. So the number of stories is the cost, and it is also the noise surface: more stories means more places for a diff to flake. I ended up paying a lot, which made me think about whether there were ways to optimise it. There were. Here they are. The core idea: combine states into one story The naive pattern is one story per variant times state times theme. A component with 5 sizes, 3 states, and 2 themes is 30 snapshots the naive way. The whole idea below is to collapse that matrix into a handful of stories while keeping full coverage. Move 1: one gallery story, not N stories For something like a Button, there is no need to have separate Primary, Secondary, and Tertiary stories. I prefer one AllVariants story that maps through the prop combinations and renders them in a grid. One snapshot then covers the entire matrix. As a bonus you get a nice grid that shows every permutation at a glance, with no extra clicks to see the variations. /

2026-08-05 原文 →
AI 资讯

How to Actually A/B Test AI Avatar vs. Text Chat Conversion (A Technical Approach)

Following up on a common claim in the AI avatar space — that voice/video avatars convert better than plain text chat — there's surprisingly little rigorous testing behind it. If you're building or embedding one of these widgets, here's a practical way to actually measure it instead of trusting vendor case studies. Why This Is Harder Than a Normal A/B Test Standard A/B testing swaps one variable (a button color, a headline) while holding everything else constant. Avatar vs. text chat isn't that clean — you're changing interaction modality, response latency expectations, and visual real estate simultaneously. You need to isolate the variable that actually matters: does voice/video presence drive conversion, independent of the underlying conversation quality? A Cleaner Experimental Setup javascript // Pseudocode for variant assignment function assignVariant(sessionId) { const hash = hashSessionId(sessionId); return hash % 2 === 0 ? 'avatar' : 'text'; } Key controls to hold constant across both variants: Same LLM backend and prompt/knowledge base — the conversation logic shouldn't differ, only the presentation layer Same lead capture form and CTA placement — don't let UI differences beyond avatar-vs-text confound the result Same traffic source — segment by acquisition channel if traffic mix varies, since paid vs. organic visitors convert differently regardless of chat UI Minimum sample size before evaluating — novelty effects are real; running this for 3 days will overstate the avatar's lift. Run for at least 2-3 weeks to let novelty decay. Metrics to Track (Not Just Conversion Rate) Conversion rate alone hides why one variant wins or loses: session_start_to_first_message (engagement friction) message_count_per_session (depth of interaction) time_to_form_completion (avatar/video adds latency — does it cost or gain time?) bounce_rate_before_first_response lead_quality_score (if you can grade downstream — a lead isn't a conversion if it's junk) A common finding worth watc

2026-08-05 原文 →
AI 资讯

Four things that surprised me running Python in the browser

I built a debugging-practice site where student code runs entirely in the browser . Python via Pyodide , JavaScript in a worker. No server executes anything. No execution bill, no queue, no sandbox to maintain. But four things bit me hard. 1. Your arguments aren't Python objects Pass a JS object into Python and you get this: TypeError: 'pyodide.ffi.JsProxy' object is not subscriptable It's not a dict . It's a live view of the JS object, and it supports neither obj[key] nor .get() . Convert explicitly: const pyArgs = input . map (( arg ) => pyodide . toPy ( arg )); const result = fn (... pyArgs ); 2. null is not None This one passed my entire test suite while being broken in production. pyodide . toPy ( null ) check result type(v) JsNull bool(v) False ✅ falsy, as expected v is None False ❌ the surprise It's falsy, so truthiness checks work fine. But is None fails — which was exactly what my code was checking. Why my tests missed it: the harness used json.loads . The app used toPy . Different conversion paths, different answers. If you need a real None , create it in Python. Don't pass one across. 3. sys.settrace is a free step debugger Want to show users their code running line by line? Python basically hands it to you: def _tracer ( frame , event , arg ): if frame . f_code . co_name != target : return None # skip library frames if event == " line " : steps . append ({ " line " : frame . f_lineno , " locals " : dict ( frame . f_locals ), }) return _tracer Two things this naive version gets wrong: Add a step cap. A tight loop generates steps faster than it burns a 5-second timeout. You need both guards. Handle exception . During unwinding, the return event still fires with arg=None . Miss it and your trace says "returned None" for code that crashed. 4. Your snapshots are lying A user screenshot exposed this one. Every step in the trace showed the final state of a list. Step 1 included mutations that hadn't happened yet. tracing: nums = []; nums.append(1); nums.append(

2026-08-05 原文 →
AI 资讯

Browser vs Node — Where the Event Loop Actually Diverges (Part 2/3)

In part 1, we built the shared mental model: call stack, microtask queue, macrotask queue, and the rule that microtasks fully drain before the next macrotask runs. That model is spec-level JavaScript behavior — but it's not the whole story once you actually run code. The event loop isn't part of the JS language spec. It's part of the host environment — the browser or Node — and each one implements it differently around that shared core. This is the post most "event loop" explainers skip, because it means going past the diagram and into how each runtime is actually built. The browser: event loop meets rendering In a browser, the event loop isn't just juggling callbacks — it's also responsible for keeping the page visually responsive. That means rendering has to get a turn too, and the browser has to decide when . Here's the roughly accurate sequence per loop iteration: Execute one macrotask (a click handler, a setTimeout callback, a network event, whatever's next in the queue) Drain the entire microtask queue Maybe render a frame — the browser doesn't render after every single task; it tries to hit ~60fps and will batch work between paints Go back to step 1 The "maybe render" part is where two APIs come in that don't exist in Node at all: requestAnimationFrame(callback) — schedules a callback to run right before the next repaint. It's not a macrotask or microtask in the queue sense — it's tied directly to the rendering pipeline. Use it for anything visual (animations, DOM measurements) instead of setTimeout , because it's synced to when the browser is actually about to paint, not an arbitrary delay. requestIdleCallback(callback) — schedules a callback to run when the browser is idle, after layout and paint, with a deadline. Meant for low-priority work you don't want competing with rendering — analytics, prefetching, non-urgent DOM updates. Here's the key interaction that's easy to miss: microtasks can starve rendering. If a promise chain keeps queueing more microtask

2026-08-05 原文 →
AI 资讯

25 Programming Mistakes I Learned After 10 Years of Software Engineering

When you start as a junior developer, you think software engineering is about writing code. A few years in, you think it's about choosing the right architecture and frameworks. After ten-plus years in the trenches - shipping features, surviving on-call disasters, and watching "perfect" codebases turn into unmaintainable monsters - you realize the truth: Software engineering is mostly about managing complexity, human communication, and trade-offs. Here are 25 mistakes I made, witnessed, or had to clean up over the past decade. Hopefully, reading them saves you a few years of painful trial and error. 1. Code & Architecture 1. Abstracting Too Early The DRY (Don't Repeat Yourself) principle is heavily drilled into beginners, but premature abstraction is far worse than duplicate code. Abstracting before you have 3–4 concrete use cases leads to rigid, over-engineered abstractions that are nightmare-inducing to change. Duplication is far cheaper than the wrong abstraction. 2. Falling in Love with "Clever" Code If your code requires a three-minute internal monologue or a complex diagram just to parse a single line, it's not smart - it's a liability. Write obvious, clear, and boring code. Your future self on a 2 AM incident response call will thank you. 3. Misunderstanding the Cost of Dependencies Adding a third-party library to solve a small problem feels like a quick win. In reality, every dependency is a contract you sign with an external team. You inherit their bugs, security vulnerabilities, breaking updates, and maintenance cycles. Ask yourself: Can we build the 5% of this library we actually need in 20 lines of code? 4. Over-Architecting for Scale You Don't Have Designing a system for 10 million daily active users when you currently have 500 is a classic trap. You end up with distributed microservices, message queues, and complex caching strategies that slow down development speed by 10x. Build for today's scale, but keep the boundary clean enough to refactor tomorrow

2026-08-04 原文 →
AI 资讯

Claude Code + 300 Docs: I Built a Personal Knowledge DB With 4 Retrieval Layers. 3 Broke.

I have 312 docs in my personal knowledge DB. Tweets, arxiv abstracts, Zenn articles, blog posts, YouTube transcripts. Claude Code writes to it, reads from it, and cites out of it every day. That number is not a brag. It is the reason I finally have data on which retrieval strategy holds up in an LLM-native workflow. I tried four. The one I ship is the one I tried last and expected to lose. Three of the four broke in ways that are worth naming, because the broken versions are what most tutorials will tell you to build. The setup, so we agree on what got benchmarked The knowledge DB is called context-forge internally. It is a folder, some markdown files, and a SQLite table. Claude Code adds to it via CLI, searches via CLI, and reads the underlying markdown directly when it needs the full text. It took eight hours to build the CLI, three months to accumulate the 312 documents at a pace of one to five per day, and about 15 minutes a day of my time to keep it flowing. Each doc has metadata: source URL, a credibility score 1-5, one to three categories, a short summary. The autoregistration pipeline is Claude Code itself: I paste a URL, it fetches, summarizes, scores, categorizes, writes the markdown, commits, and updates the SQLite index. The pipeline is not the interesting part. The retrieval strategy is. I ran each of the four strategies for two weeks against the same day-to-day tasks: writing a chapter, answering "what did that person say about X," and building an argument for a decision. Same me, same DB, different retriever. Layer 1: pure semantic RAG (vector embeddings). Broke at 200 docs The first version was the textbook answer. Embed every document with a sentence transformer, store the vectors in SQLite with a similarity index, retrieve the top-k on every query. This is the pattern Silicon Slopes covers for code-level RAG and Anthropic itself has an issue open for a built-in version . It worked at 50 docs. It worked at 100. Around 200 documents it started retrie

2026-08-04 原文 →
AI 资讯

I built an invoice generator with no backend — the whole app is one HTML file

Every invoicing tool I tried wanted an account, a subscription, and a copy of my client list on its servers — then charged me monthly to put my own logo on my own invoice. So I built the opposite. Billfold is a complete invoice generator that runs entirely in your browser. No account, no backend, no build step. The whole app is a single index.html file you could email to yourself. It's MIT-licensed and the source is right here: github.com/quantum-hacker0/billfold . Here are the three parts that were actually fun to build. 1. "No server" isn't a privacy policy — it's the architecture The usual pitch is "we take your privacy seriously." That's a promise you have to trust. I wanted it to be a fact you can verify : Open DevTools → Network, create an invoice, and count the requests. It's zero. There's nothing to upload because there's nowhere to upload it. Data lives in localStorage . The app is HTML/CSS/JS inlined into one file — no framework, no bundler, no node_modules . Download it once and it works offline forever. 2. Sharing an invoice without a database — put it in the URL hash This was the interesting constraint. How do you send someone a view-only invoice when you have no server to store it on? The trick: encode the whole document into the URL hash fragment . The fragment (everything after # ) is the one part of a URL that browsers never send to the server — it stays client-side. function shareLink ( state ) { const json = JSON . stringify ( state ); const encoded = btoa ( unescape ( encodeURIComponent ( json ))) . replace ( / \+ /g , ' - ' ). replace ( / \/ /g , ' _ ' ). replace ( /=+$/ , '' ); // base64url return location . origin + location . pathname + ' #v= ' + encoded ; } The recipient's browser reads the fragment, decodes it, and renders the invoice locally. The data rides inside the link and never touches a host — not even mine. PDF export, by the way, is just window.print() with a print stylesheet. 3. Invoices as URLs — with an npm package Because the a

2026-08-04 原文 →
开发者

JavaScript Interview Questions Every Dev Should Know — Part 2: Functions, Scope & Closures

Welcome to Part 2 of the JS interview series! This time we're tackling functions, scope, and the topic that trips up even experienced developers in interviews: closures . Missed Part 1? Check out Fundamentals & Data Types first. Q1. What is a closure? A closure is what happens when an inner function "remembers" and continues to have access to the variables from its enclosing (outer) function's scope, even after that outer function has already finished running and would normally have had its local variables cleaned up. This works because JavaScript functions don't just capture the values of outer variables — they capture live references to them, keeping the entire surrounding scope alive in memory for as long as the inner function itself is reachable. Closures are one of the most powerful and commonly used patterns in JavaScript. They're the mechanism behind data privacy (since variables inside a closure can't be accessed from outside except through the functions that were given access), factory functions that generate customized functions, memoization caches, and event handler callbacks that need to remember state from when they were created. In the classic counter example below, each call to counter() creates a fresh, independent count variable that only the returned function can see or modify — there's no way to reach into it from outside. function counter () { let count = 0 ; return () => ++ count ; } const inc = counter (); inc (); // 1 inc (); // 2 Q2. What is lexical scoping? Lexical scoping (also called static scoping) means that a variable's accessibility is determined entirely by where it's physically written in your source code — not by which function called which, or the order in which functions happen to execute at runtime. When JavaScript compiles your code, it can already determine, just by looking at the nesting of functions and blocks, exactly which variables any given piece of code will be able to see. This is what allows an inner function to "reach

2026-08-04 原文 →
AI 资讯

Scope Is Never Fixed — Why Specification Ambiguity (Not Scope Creep) Is the Real Fixed-Price Problem

Software projects fail on fixed-price contracts. This is not a controversial statement — the Standish Group's CHAOS report has tracked this for decades, showing that only 31% of software projects succeed on time and on budget, while 50% are challenged and 19% fail outright. But the conventional wisdom about why they fail — scope creep — misses the real problem. Scope creep is a symptom. The real disease is specification ambiguity . The Map Is Not the Territory Paweł Brodziński, an experienced software delivery leader, captured this perfectly with a simple analogy. A specification is a map of the software you want to build. And as with any map, its representation of the terrain is necessarily imperfect. For a perfect map, it would have to be as large as the terrain itself. "The only absolutely precise specification of a software project is the code itself. But if you already have that, why would you buy it?" When you write "As a workspace owner, I can set administrative privileges to workspace members," two people reading that sentence will envision different things. One imagines a simple dropdown with three permission levels. The other imagines role-based access control with custom policies, audit logs, and delegation. Both are reasonable interpretations of the same text. The PMI's research on communications complexity confirms why this happens: the number of communication paths grows geometrically with project size ( n(n-1)/2 ), and every path is a channel where ambiguity can creep in. Even a simple conversation involves encoding, decoding, and filtering — two receivers can interpret the same message differently. Why This Is Not Scope Creep Scope creep is when a client asks for something new after the contract is signed. That's a well-understood problem with well-understood countermeasures: change requests, sign-offs, contingency buffers. Specification ambiguity is different. It's not about adding new things — it's about both parties believing they agreed on the sa

2026-08-04 原文 →
AI 资讯

The Art of Range Pricing in Software Projects: A Practical Guide for Agencies

Every software agency has been here: the client asks for a price, you give a range (say $45k–$65k), and two things can happen. Either the client nods and you win the deal at the low end — or they get suspicious and ask "so you don't actually know how much it costs?" Range pricing is often misunderstood. Used wrong, it looks like you're guessing. Used right, it's the most honest and professional way to price software projects — because anyone who gives you a single fixed number for an undefined project is either padding heavily or gambling with their margin. This guide covers when to use range pricing, how to structure it, and — most importantly — how to present it so clients trust you more, not less. Why Single-Point Pricing Is a Problem A fixed price for an undefined project forces you into one of two positions: You pad aggressively — add 40% contingency, quote $70k for a project you'd happily do for $50k. If the scope doesn't expand, the client overpays. If it does, you're protected. Either way, one party loses. You guess lean — quote $50k based on your best assumptions. If the client adds features mid-project, your margin evaporates. The client thinks they're paying for X, you're building X+Y. Both parties end up frustrated. A pricing range avoids both traps. It says: "based on what we know today, this project falls between $45k and $65k. Here's what needs to be true for the low end, and here's what would push it toward the high end." That's not guesswork. That's transparency. The Anatomy of a Good Pricing Range Not all ranges are created equal. A useful range has three properties: 1. Width That Respects Uncertainty The width of your range communicates how well you understand the project. Range width What it signals When it's appropriate < 15% ($50k–$57k) High confidence Detailed spec, similar past projects, known team 15–30% ($50k–$65k) Moderate confidence Clear brief, some unknowns in tech or integration 30–50% ($50k–$75k) Low confidence Vague brief, new domain

2026-08-04 原文 →
AI 资讯

AWS Introduction for Beginner Software Engineers

As a software engineer starting with AWS, you might feel overwhelmed by all the services. Let me break down the key components with real-world examples to help you get started. 1. DNS & How AWS Route 53 Works Problem: Users can't remember IP addresses like 54.210.167.101 for your app. Solution: AWS Route 53 (DNS service) maps yourdomain.com to your servers. Real example: Your startup has servers in Ohio and Frankfurt. Route 53 automatically sends European users to Frankfurt and routes US traffic to Ohio — faster load times for everyone. 2. Networking: VPC & Subnets VPC: Your private cloud network (like an office building). Public subnet: For web servers (needs internet access). Private subnet: For databases (blocked from direct internet access). Internet Gateway: Connects public subnets to the internet. NAT Gateway: Lets private subnets reach the internet (one-way). Real example: In your e-commerce app, the web server runs in a public subnet while the database sits in a private subnet. 3. Storing & Delivering Static Files (S3 + CloudFront) Amazon S3: Stores images, videos, and logs. CloudFront (CDN): Caches content globally for faster loading. Real example: Your blog hosts images in S3; CloudFront caches them in 450+ locations, so a reader in Tokyo gets images from Japan instead of Virginia — cutting load time by ~50%. Pro tip: Enable S3 Versioning to recover accidentally deleted files. 4. Running Backend Services AWS Lambda (Serverless) — best for event-driven tasks. Example: a photo app resizes images automatically on upload. EC2 (Virtual Servers) — best for full control (custom OS, legacy apps). Example: hosting a Java monolith with specific dependencies. ECS/EKS (Containers) — best for microservices (Docker/Kubernetes). Example: a food-delivery app with separate services for orders, payments, and tracking. 5. Databases: Picking the Right One Amazon RDS (SQL): Structured data with relationships — e.g. user accounts + orders. DynamoDB (NoSQL): High-speed, scalable

2026-08-04 原文 →