You declare a metadata type marking rate-limited operations. Why does its declaration name the kinds of declarations it may be attached to?
answer
- markers are not free-floating
- the declaration lists legal sites
- declaration kinds, not values
- misplaced marker is an error
- widen later, never narrow
basics
~20 sA metadata type's declaration enumerates the declaration kinds it may be attached to - type, method, field, parameter - and attachments anywhere else are rejected. Target lists turn a misplaced marker into a build error instead of a silent no-op.
solid answer
~50 sA metadata type is a declaration in its own right, and part of that declaration is the set of declaration kinds it may legally be attached to. A rate-limit marker makes sense on an operation, and on the type that groups operations; it means nothing on a local variable or a parameter. Naming those targets lets the toolchain check every attachment site, so an engineer who puts the marker one line too high gets an error rather than a marker that nothing will ever act on. That matters because metadata fails quietly by nature: attaching it executes nothing, so the checks the declaration asked for are most of the feedback you get. For a shared marker, start with the narrowest target list that covers real use - widening it later is compatible, narrowing it invalidates attachments you cannot see.
code
pseudocode · 10 linesmetadata type RateLimited
targets: method, type
member permitsPerSecond: number
mark RateLimited(permitsPerSecond = 10)
function chargeCard(order)
...
mark RateLimited(permitsPerSecond = 10)
local attempts = 0 // rejected: local is not a listed targetgo deeper
Recall that a metadata type declares which kinds of declaration it may sit on, and that putting it elsewhere is rejected rather than tolerated.
Explain where the check happens and when: the attachment site is compared against the declared list before any reader is involved, so nothing needs to run for it to fail.
Show that you treat the target list as part of a published contract: widening is compatible, narrowing breaks attachments in code you do not own, and each accepted site needs a written meaning.
Frame it as the cheapest guard available against a failure mode with no symptom, and weigh it against the cost of every extra site a toolkit must then inspect and honour.
## A metadata type is a declaration with rules Attaching metadata to code looks like decoration, but the thing being attached is a **declared type**. Declaring it is a deliberate design act, and the declaration answers four questions before anyone writes the first attachment: - **What is it called** - the one name every attachment site and every reader agrees on. - **What does it carry** - its `member elements`, such as a permit rate or a scope. - **Where may it be attached** - the declaration kinds in its **target list**. - **May it repeat** - whether two attachments of it on one declaration are legal. The target list is the rule a newcomer meets first, because it is the rule that produces an error message. ## What the target list actually does The target list enumerates declaration kinds: a type, a method or function, a constructor, a field, a parameter, a local variable, a whole module, and - because a metadata type is itself a declaration - a metadata type. The toolchain compares each attachment site against that list. For a toolkit marker that says "this operation is rate limited", the list is a design decision with real content: | Attachment site | What the marker would mean there | Worth targeting? | |---|---|---| | Method | this one operation is rate limited | yes - the core case | | Type | every operation on this type is limited by default | yes - the grouping case | | Parameter | this argument is rate limited | no - no reader could act on it | | Local variable | a value inside one call is limited | no - invisible outside the body | Two things follow from writing the list down. First, a misplaced attachment fails **at the site**, with a file and a line, in the code the author is already editing. Second, the list is documentation with teeth: it tells a reader of the metadata type exactly which shapes of use the toolkit promises to honour. ## Why enforcement matters more for metadata than for ordinary code Ordinary code announces its own mistakes: a call to something that does not exist fails, a wrong argument type fails. **Attaching metadata executes nothing.** A marker sitting on the wrong declaration looks exactly like a marker sitting on the right one - same spelling, same members, same review approval - and the difference only shows up as behaviour that never happened. A rate limit that was never applied is not an error anywhere; it is a service that quietly accepted ten times the traffic you thought it would. The target list is the earliest guard against that. It fires without any reader being involved, without the toolkit being on the classpath at all in some designs, and without the marked code ever being executed. ## Choosing the list for a shared marker 1. **Start narrow.** List only the sites the toolkit actually inspects today. A target you accept but never read is a promise you are not keeping. 2. **Remember the compatibility direction.** Adding a kind to the list is compatible - every existing attachment is still legal. Removing a kind is breaking - attachments already written on that kind stop compiling, including ones in code you do not own. 3. **Give each accepted site a distinct, written meaning.** If the marker is legal on both a method and its type, say what happens when both carry it; "the nearer one wins" is a decision, and an unwritten decision is a bug report waiting. 4. **Do not accept a site to be accommodating.** Every extra kind is another place a reader must look, and another place a marker can sit doing nothing. ## Where systems differ Some metadata systems treat the attachment as a purely declarative construct checked when the code is compiled, so a bad site is a compile error. Others treat the attachment as an ordinary construction evaluated when the declaration is first loaded, in which case the only check is whatever the metadata type performs for itself at that moment, and the failure arrives later and further away. The mechanism you are being asked about is the same in both: **the metadata type declares where it belongs, and something enforces that before a reader is involved.** What differs is how early the enforcement lands, and an engineer choosing between designs should know that earlier is cheaper.
- What do you gain from a build error over an attachment that is simply ignored?Location and timing. The error names the file and line while the author is still in that code, before review, before deployment. An ignored attachment produces no signal at all, and its only symptom is a behaviour that never occurred - which is indistinguishable from a behaviour that was never wanted.
- The marker is legal on both a method and the type that declares it. What must the declaration settle?Precedence and combination. Decide whether the nearer attachment replaces the outer one, whether the outer one applies to methods that carry nothing, and whether the two ever merge member by member. Write it next to the target list; if it is unwritten, each reader in the toolkit will guess differently.
saying these in an interview costs you the question
- Says a target list is documentation the toolchain does not enforce
- Thinks a marker on an unsupported declaration is quietly ignored later
- Assumes any marker may be attached to any kind of declaration
- Claims narrowing a published marker's target list is a safe change
- Believes attaching metadata executes something at the attachment site