[{"data":1,"prerenderedAt":271},["ShallowReactive",2],{"list-\u002Fblog-en":3},[4,85,204],{"entry":5,"writtenIn":84,"onlyIn":75},{"id":6,"title":7,"body":8,"date":69,"description":70,"extension":71,"meta":72,"navigation":73,"path":74,"role":75,"seo":76,"stack":77,"stem":78,"tags":79,"year":75,"__hash__":83},"content_en\u002Fblog\u002Fthe-eight-hour-interface.md","The eight-hour interface",{"type":9,"value":10,"toc":62},"minimark",[11,15,18,23,26,29,33,40,46,52,56,59],[12,13,14],"p",{},"Most interface advice is written for software people meet once. A landing page has six seconds to explain itself. A checkout flow is judged on whether a stranger can finish it without thinking.",[12,16,17],{},"Enterprise software is the opposite case. The same person opens the same screen every morning for three years. They stop reading labels after the first week. They learn the position of things, not their names.",[19,20,22],"h2",{"id":21},"what-stops-mattering","What stops mattering",[12,24,25],{},"Onboarding polish stops mattering almost immediately. A tooltip that explains a field is read once and never again, but it occupies space forever and it has to be maintained in two languages.",[12,27,28],{},"Visual novelty stops mattering too. A control that is delightful the first time is friction the four-hundredth time, because delight is a small interruption and interruptions compound.",[19,30,32],{"id":31},"what-starts-mattering","What starts mattering",[12,34,35,39],{},[36,37,38],"strong",{},"Position stability."," If a button moves between releases, every user pays for it. Muscle memory is the actual interface after week two, and it is undocumented.",[12,41,42,45],{},[36,43,44],{},"Density."," Six seconds of attention rewards whitespace. Eight hours rewards seeing more rows without scrolling. The comfortable default is usually too generous for someone who does this for a living.",[12,47,48,51],{},[36,49,50],{},"Failure legibility."," A stranger who hits an error abandons the task. A daily user has to recover from it and keep going. So the question is not \"does this look alarming enough\" but \"does this tell me which record broke and what I do next\".",[19,53,55],{"id":54},"the-part-that-is-hard-to-sell","The part that is hard to sell",[12,57,58],{},"None of this photographs well. A dense table with stable column positions and blunt error text does not win a redesign presentation. It just costs the people who use it fewer minutes per day, and there are a lot of days.",[12,60,61],{},"That trade is worth making explicit early, because otherwise it gets relitigated every time someone new looks at a screenshot.",{"title":63,"searchDepth":64,"depth":64,"links":65},"",2,[66,67,68],{"id":21,"depth":64,"text":22},{"id":31,"depth":64,"text":32},{"id":54,"depth":64,"text":55},"2026-07-18","Enterprise software is used for a whole working day, not scanned for six seconds. That single fact changes almost every design decision.","md",{},true,"\u002Fblog\u002Fthe-eight-hour-interface",null,{"title":7,"description":70},[],"blog\u002Fthe-eight-hour-interface",[80,81,82],"sapui5","ux","enterprise","T3sGy0ozg1Bk5PFdbC6ohj1C7UTWOQ0wclaN9kbGXyg","en",{"entry":86,"writtenIn":84,"onlyIn":75},{"id":87,"title":88,"body":89,"date":194,"description":195,"extension":71,"meta":196,"navigation":73,"path":197,"role":75,"seo":198,"stack":199,"stem":200,"tags":201,"year":75,"__hash__":203},"content_en\u002Fblog\u002Ftypescript-into-a-sapui5-codebase.md","TypeScript into a SAPUI5 codebase",{"type":9,"value":90,"toc":189},[91,94,98,101,148,151,154,158,165,168,172,175,182,185],[12,92,93],{},"SAPUI5 predates the assumption that a frontend codebase is typed. Its module system, its class definitions, and its XML views were all designed for a world where the editor could not help you. Types can be added, but not evenly — some parts of the framework reward them immediately, and some resist.",[19,95,97],{"id":96},"where-it-pays-immediately","Where it pays immediately",[12,99,100],{},"Model access is the clearest win. A line like this is where most of the runtime bugs live:",[102,103,107],"pre",{"className":104,"code":105,"language":106,"meta":63,"style":63},"language-ts shiki shiki-themes henricus","const rate = model.getProperty(\"\u002Fheader\u002FexchangeRate\");\n","ts",[108,109,110],"code",{"__ignoreMap":63},[111,112,115,119,123,126,129,133,136,139,143,145],"span",{"class":113,"line":114},"line",1,[111,116,118],{"class":117},"s5glF","const",[111,120,122],{"class":121},"s6eg1"," rate ",[111,124,125],{"class":117},"=",[111,127,128],{"class":121}," model.",[111,130,132],{"class":131},"sNWak","getProperty",[111,134,135],{"class":121},"(",[111,137,138],{"class":121},"\"",[111,140,142],{"class":141},"s3_7c","\u002Fheader\u002FexchangeRate",[111,144,138],{"class":121},[111,146,147],{"class":121},");\n",[12,149,150],{},"Everything about it is a guess: whether the path exists, whether it is a number, whether it can be null after a failed load. Typing the model shape moves all three guesses into the editor.",[12,152,153],{},"Formatters and OData calls follow. Both are boundaries — data crosses them and changes shape — and boundaries are exactly where a type is worth the keystrokes.",[19,155,157],{"id":156},"where-it-turns-into-ceremony","Where it turns into ceremony",[12,159,160,161,164],{},"Controller lifecycle methods gain almost nothing. ",[108,162,163],{},"onInit"," takes no arguments and returns nothing; typing it is filling in a form.",[12,166,167],{},"XML views are the real limit. A view binds to a controller method by string name, and no compiler checks that string. You can type the controller perfectly and still ship a view that calls a method deleted three commits ago. Types give a strong impression of safety across a gap they never cross.",[19,169,171],{"id":170},"what-i-would-tell-myself-at-the-start","What I would tell myself at the start",[12,173,174],{},"Type the data, not the framework. Model shapes, service responses, formatter inputs and outputs — those catch real defects.",[12,176,177,178,181],{},"Resist typing the parts that exist only to satisfy the framework. Every ",[108,179,180],{},"any"," you eliminate there costs a maintenance burden and returns nothing, and it makes the diff long enough that reviewers skim it.",[12,183,184],{},"The goal was never full coverage. It was knowing what shape the data is when it reaches the screen.",[186,187,188],"style",{},"html pre.shiki code .s5glF, html code.shiki .s5glF{--shiki-default:#E8D8A6}html pre.shiki code .s6eg1, html code.shiki .s6eg1{--shiki-default:#EDEBE3}html pre.shiki code .sNWak, html code.shiki .sNWak{--shiki-default:#C9A227}html pre.shiki code .s3_7c, html code.shiki .s3_7c{--shiki-default:#7BA697}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":63,"searchDepth":64,"depth":64,"links":190},[191,192,193],{"id":96,"depth":64,"text":97},{"id":156,"depth":64,"text":157},{"id":170,"depth":64,"text":171},"2026-05-02","Adding types to a framework built before types were expected — where it pays off, and where it turns into ceremony.",{},"\u002Fblog\u002Ftypescript-into-a-sapui5-codebase",{"title":88,"description":195},[],"blog\u002Ftypescript-into-a-sapui5-codebase",[80,202],"typescript","byv7yaXN7-Xfci9bH0WHPjdA5OfpNFwqdXWzty8ztB8",{"entry":205,"writtenIn":84,"onlyIn":84},{"id":206,"title":207,"body":208,"date":260,"description":261,"extension":71,"meta":262,"navigation":73,"path":263,"role":75,"seo":264,"stack":265,"stem":266,"tags":267,"year":75,"__hash__":270},"content_en\u002Fblog\u002Fwhat-review-taught-me.md","What review taught me",{"type":9,"value":209,"toc":255},[210,213,217,220,223,227,233,239,245,249,252],[12,211,212],{},"I expected code review to make me better at spotting bugs in other people's work. It did, a little. What it actually changed was how I open a pull request.",[19,214,216],{"id":215},"reading-is-slower-than-writing","Reading is slower than writing",[12,218,219],{},"The author has the whole change loaded in their head. The reviewer has a diff, in file-alphabetical order, with no idea which part is the point.",[12,221,222],{},"That asymmetry is the entire problem, and almost every review frustration traces back to it. A reviewer who cannot find the point will either approve without reading or ask questions the author considers obvious. Both outcomes are the author's to prevent.",[19,224,226],{"id":225},"three-habits-that-came-out-of-it","Three habits that came out of it",[12,228,229,232],{},[36,230,231],{},"Separate the mechanical commit from the thinking commit."," A rename touching forty files and a logic change touching one should never arrive together. Reviewed separately, both are quick; reviewed together, the logic change is invisible.",[12,234,235,238],{},[36,236,237],{},"Say what you decided against."," \"I did not use a computed here because the value is read once during setup\" prevents the most common review comment before it is written. It costs one line.",[12,240,241,244],{},[36,242,243],{},"Point at the risky part."," Every change has one. Naming it is not an admission of weakness — it is directing the limited attention the reviewer has toward the place where it pays.",[19,246,248],{"id":247},"the-uncomfortable-part","The uncomfortable part",[12,250,251],{},"Most review comments I received were things I already knew and had skipped. Not knowledge gaps — attention gaps, at the end of a task when it felt done.",[12,253,254],{},"That is a harder problem than not knowing something, because you cannot read your way out of it. The only fix I have found is mechanical: read the diff yourself, in the review interface, before assigning anyone. Half the comments never get written.",{"title":63,"searchDepth":64,"depth":64,"links":256},[257,258,259],{"id":215,"depth":64,"text":216},{"id":225,"depth":64,"text":226},{"id":247,"depth":64,"text":248},"2026-03-09","Two years of reading other people's diffs, and the habit it changed most was how I write my own.",{},"\u002Fblog\u002Fwhat-review-taught-me",{"title":207,"description":261},[],"blog\u002Fwhat-review-taught-me",[268,269],"review","process","1TKANv2FoS2u9-WjFuhdsWOX7k8q2IOPrDwSSQn5uQ0",1788956392049]