[{"data":1,"prerenderedAt":1191},["ShallowReactive",2],{"article-alternates":3,"article-\u002Ftr\u002Flifestyle\u002Fcode-review-kulturu-olculebilir-kalite-kisisel-catisma-yok":13},{"i18nKey":4,"paths":5},"lifestyle-003-2026-05",{"de":6,"en":7,"es":8,"fr":9,"it":10,"ru":11,"tr":12},"\u002Fde\u002Flifestyle\u002Fcode-review-kultur-messbare-qualitaet","\u002Fen\u002Flifestyle\u002Fcode-review-culture-measurable-quality-no-personal-conflict","\u002Fes\u002Flifestyle\u002Fcodigo-resena-cultura-calidad-medible-sin-conflictos-personales","\u002Ffr\u002Flifestyle\u002Fculture-revue-code-qualite-mesurable","\u002Fit\u002Flifestyle\u002Fcode-review-kultur-olculebilir-kalite","\u002Fru\u002Flifestyle\u002Fcode-review-kulturi-olculebilir-kalite","\u002Ftr\u002Flifestyle\u002Fcode-review-kulturu-olculebilir-kalite-kisisel-catisma-yok",{"_path":12,"_dir":14,"_draft":15,"_partial":15,"_locale":16,"title":17,"description":18,"publishedAt":19,"modifiedAt":19,"category":14,"i18nKey":4,"tags":20,"readingTime":26,"author":27,"body":28,"_type":1185,"_id":1186,"_source":1187,"_file":1188,"_stem":1189,"_extension":1190},"lifestyle",false,"","Code Review Kültürü: Ölçülebilir Kalite, Kişisel Çatışma Yok","Time-to-review, comment density, PR size kuralları ile code review sürecini kişisel yorumdan arındırıp ölçülebilir ekip standardına dönüştürme rehberi.","2026-05-13",[21,22,23,24,25],"code-review","engineering-culture","team-workflow","quality-metrics","async-collaboration",8,"Roibase",{"type":29,"children":30,"toc":1174},"root",[31,39,46,68,73,109,114,130,136,141,146,233,243,253,263,270,275,281,286,294,337,342,376,386,392,397,440,445,1004,1009,1015,1020,1028,1051,1059,1082,1087,1093,1098,1106,1114,1119,1127,1132,1142,1152,1157,1163,1168],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36],{"type":37,"value":38},"text","Code review'ın \"yapıcı eleştiri\" olduğu söylenir ama pratikte ekiplerin %60'ından fazlası subjektif tartışmalarla zaman kaybeder. Bir PR'a 15 yorum gelir, 8'i stil, 3'ü mimari tercih, gerçek bug bulan 2'dir. Asıl sorun: kişisel zevk ile ekip standardı arasında net çizgi yok. Roibase'de 8+ yıllık ekip liderliği deneyimi gösterdi ki review kalitesi ölçülemiyorsa, kişisel çatışmaya evrilir. Bu yazı time-to-review, comment density, PR size gibi sayısal kuralları nasıl sistematik kültüre dönüştüreceğinizi anlatıyor.",{"type":32,"tag":40,"props":41,"children":43},"h2",{"id":42},"subjektif-yorumdan-sistematik-standarda-geçiş",[44],{"type":37,"value":45},"Subjektif yorumdan sistematik standarda geçiş",{"type":32,"tag":33,"props":47,"children":48},{},[49,51,58,60,66],{"type":37,"value":50},"Code review'da \"bence\", \"daha iyi olabilir\", \"ideal değil\" gibi ifadeler kültürü yavaşlatır. Şu senaryo sık yaşanır: backend developer ",{"type":32,"tag":52,"props":53,"children":55},"code",{"className":54},[],[56],{"type":37,"value":57},"map()",{"type":37,"value":59}," yerine ",{"type":32,"tag":52,"props":61,"children":63},{"className":62},[],[64],{"type":37,"value":65},"forEach()",{"type":37,"value":67}," kullanan kodu reject eder, frontend developer \"performance artışı %0.2 — optimize etmeyelim\" der, 6 mesaj gidip gelir. 45 dakika kayıp, karar yok.",{"type":32,"tag":33,"props":69,"children":70},{},[71],{"type":37,"value":72},"Çözüm: review kriterlerini ölçülebilir hale getirin. \"Kötü kod\" tanımı yerine sayısal eşikler koyun. Örneğin Roibase ekibinde şu kurallar standart:",{"type":32,"tag":74,"props":75,"children":76},"ul",{},[77,89,99],{"type":32,"tag":78,"props":79,"children":80},"li",{},[81,87],{"type":32,"tag":82,"props":83,"children":84},"strong",{},[85],{"type":37,"value":86},"Cyclomatic complexity >10:",{"type":37,"value":88}," otomatik reject (SonarQube kontrolü)",{"type":32,"tag":78,"props":90,"children":91},{},[92,97],{"type":32,"tag":82,"props":93,"children":94},{},[95],{"type":37,"value":96},"Test coverage drop >5%:",{"type":37,"value":98}," manuel review zorunlu",{"type":32,"tag":78,"props":100,"children":101},{},[102,107],{"type":32,"tag":82,"props":103,"children":104},{},[105],{"type":37,"value":106},"Function length >50 satır:",{"type":37,"value":108}," yorum istenir (exception dokumentasyonu gerekir)",{"type":32,"tag":33,"props":110,"children":111},{},[112],{"type":37,"value":113},"Bu kurallar linter'da enforce edilir. Review yapan kişi \"bence uzun\" demez, sistem \"49 satır — kabul, 51 satır — açıklama istenir\" der. Tartışma kalkmaz, standart çalışır. Ekibin 2 aylık PR geçmişine bakarsanız reject rate %12'den %4'e düşer çünkü subjektif redler kaybolur.",{"type":32,"tag":33,"props":115,"children":116},{},[117,119,128],{"type":37,"value":118},"Önemli not: Bu sistemik yaklaşım ",{"type":32,"tag":120,"props":121,"children":125},"a",{"href":122,"rel":123},"https:\u002F\u002Fwww.roibase.com.tr\u002Ftr\u002Fbranding",[124],"nofollow",[126],{"type":37,"value":127},"markalaşma ve brand identity",{"type":37,"value":129}," sürecine benzer — tutarlılık kişisel tercihten değil, ölçülebilir kriterlerden gelir. Markanızın renk paleti hex code ile tanımlanırsa, kodunuzun da kalitesi sayısal metrikle tanımlanmalı.",{"type":32,"tag":40,"props":131,"children":133},{"id":132},"time-to-review-asenkron-ekiplerde-yanıt-disiplini",[134],{"type":37,"value":135},"Time-to-review: asenkron ekiplerde yanıt disiplini",{"type":32,"tag":33,"props":137,"children":138},{},[139],{"type":37,"value":140},"Ekibiniz remote + async çalışıyorsa review gecikmesi en büyük bottleneck'tir. Şu veri sektör ortalaması: ortalama time-to-first-review 18 saattir (GitHub 2024 raporu). Bu 18 saat boyunca PR sahibi ya bloke olur ya da yeni iş başlatır — ikisi de maliyetlidir.",{"type":32,"tag":33,"props":142,"children":143},{},[144],{"type":37,"value":145},"Roibase workflow'u:",{"type":32,"tag":147,"props":148,"children":149},"table",{},[150,174],{"type":32,"tag":151,"props":152,"children":153},"thead",{},[154],{"type":32,"tag":155,"props":156,"children":157},"tr",{},[158,164,169],{"type":32,"tag":159,"props":160,"children":161},"th",{},[162],{"type":37,"value":163},"Metrik",{"type":32,"tag":159,"props":165,"children":166},{},[167],{"type":37,"value":168},"Eşik",{"type":32,"tag":159,"props":170,"children":171},{},[172],{"type":37,"value":173},"Enforcement",{"type":32,"tag":175,"props":176,"children":177},"tbody",{},[178,197,215],{"type":32,"tag":155,"props":179,"children":180},{},[181,187,192],{"type":32,"tag":182,"props":183,"children":184},"td",{},[185],{"type":37,"value":186},"Time-to-first-review",{"type":32,"tag":182,"props":188,"children":189},{},[190],{"type":37,"value":191},"\u003C4 saat",{"type":32,"tag":182,"props":193,"children":194},{},[195],{"type":37,"value":196},"Slack uyarısı",{"type":32,"tag":155,"props":198,"children":199},{},[200,205,210],{"type":32,"tag":182,"props":201,"children":202},{},[203],{"type":37,"value":204},"Time-to-merge (approved sonrası)",{"type":32,"tag":182,"props":206,"children":207},{},[208],{"type":37,"value":209},"\u003C2 saat",{"type":32,"tag":182,"props":211,"children":212},{},[213],{"type":37,"value":214},"Pipeline bloğu",{"type":32,"tag":155,"props":216,"children":217},{},[218,223,228],{"type":32,"tag":182,"props":219,"children":220},{},[221],{"type":37,"value":222},"Review turnarında round sayısı",{"type":32,"tag":182,"props":224,"children":225},{},[226],{"type":37,"value":227},"\u003C3",{"type":32,"tag":182,"props":229,"children":230},{},[231],{"type":37,"value":232},"PR split önerisi",{"type":32,"tag":33,"props":234,"children":235},{},[236,241],{"type":32,"tag":82,"props":237,"children":238},{},[239],{"type":37,"value":240},"4 saatlik ilk review eşiği:",{"type":37,"value":242}," PR açıldığında Slack'te tag atılır, 4 saat içinde ilk yorum gelmezse escalation notification gider. Bu \"acil bakalım\" demek değil — async çalışırken her 4 saatte bir review queue check etmek disiplindir.",{"type":32,"tag":33,"props":244,"children":245},{},[246,251],{"type":32,"tag":82,"props":247,"children":248},{},[249],{"type":37,"value":250},"2 saatlik merge eşiği:",{"type":37,"value":252}," PR approve edildikten sonra merge işlemi 2 saat içinde yapılmazsa otomatik merge açılır (test pass + approval varsa). Bu \"unutulmuş PR\" senaryosunu öldürür.",{"type":32,"tag":33,"props":254,"children":255},{},[256,261],{"type":32,"tag":82,"props":257,"children":258},{},[259],{"type":37,"value":260},"3 round kuralı:",{"type":37,"value":262}," PR'da 3. yorum turunu açıyorsa, ya PR çok büyüktür ya da scope belirsizdir. Sistem otomatik \"split PR\" önerisi sunar. Böylece 300 satırlık PR 2×150'ye bölünür, review daha hızlı kapanır.",{"type":32,"tag":264,"props":265,"children":267},"h3",{"id":266},"async-yanıt-protokolü-örneği",[268],{"type":37,"value":269},"Async yanıt protokolü örneği",{"type":32,"tag":33,"props":271,"children":272},{},[273],{"type":37,"value":274},"Developer A sabah 09:00 PR açar. Developer B öğleden sonra 13:30 review yapar (4 saat içinde). A akşam 18:00 düzeltir. B ertesi sabah 09:30 final check yapar. Toplam 24.5 saat süreç ama hiç senkron toplantı yok, hiç kimse bloke değil. Time-to-merge: 1.5 iş günü. Bu hız async kültürde mükemmeldir.",{"type":32,"tag":40,"props":276,"children":278},{"id":277},"pr-size-ve-comment-density-büyük-pr-kötü-prdır",[279],{"type":37,"value":280},"PR size ve comment density: büyük PR kötü PR'dır",{"type":32,"tag":33,"props":282,"children":283},{},[284],{"type":37,"value":285},"Büyük PR review edilemez. GitHub verisi: 400+ satır değişiklik içeren PR'larda reviewer dikkat süresi 12 dakikaya düşer (200 satırlık PR'da 28 dakika). Yani 2 katı değişiklik için yarısı dikkat.",{"type":32,"tag":33,"props":287,"children":288},{},[289],{"type":32,"tag":82,"props":290,"children":291},{},[292],{"type":37,"value":293},"PR size kuralı:",{"type":32,"tag":74,"props":295,"children":296},{},[297,307,317,327],{"type":32,"tag":78,"props":298,"children":299},{},[300,305],{"type":32,"tag":82,"props":301,"children":302},{},[303],{"type":37,"value":304},"Küçük (0-100 satır):",{"type":37,"value":306}," ideal, tek oturumda review",{"type":32,"tag":78,"props":308,"children":309},{},[310,315],{"type":32,"tag":82,"props":311,"children":312},{},[313],{"type":37,"value":314},"Orta (100-250 satır):",{"type":37,"value":316}," kabul edilir, 2 oturumda review",{"type":32,"tag":78,"props":318,"children":319},{},[320,325],{"type":32,"tag":82,"props":321,"children":322},{},[323],{"type":37,"value":324},"Büyük (250-400 satır):",{"type":37,"value":326}," split önerisi, justification gerekir",{"type":32,"tag":78,"props":328,"children":329},{},[330,335],{"type":32,"tag":82,"props":331,"children":332},{},[333],{"type":37,"value":334},"Çok büyük (>400 satır):",{"type":37,"value":336}," otomatik reject, refactor zorunlu",{"type":32,"tag":33,"props":338,"children":339},{},[340],{"type":37,"value":341},"Ekipte \"küçük PR\" kültürü kurmak için şu taktikler işler:",{"type":32,"tag":343,"props":344,"children":345},"ol",{},[346,356,366],{"type":32,"tag":78,"props":347,"children":348},{},[349,354],{"type":32,"tag":82,"props":350,"children":351},{},[352],{"type":37,"value":353},"Feature flagging:",{"type":37,"value":355}," Yeni özelliği canlıya kapalı şekilde küçük PR'larla ekle. Son PR flag'i açar.",{"type":32,"tag":78,"props":357,"children":358},{},[359,364],{"type":32,"tag":82,"props":360,"children":361},{},[362],{"type":37,"value":363},"Stacked PRs:",{"type":37,"value":365}," PR1 merge olmadan PR2 açılabilir, ancak PR2 base branch'i PR1'dir. Linear dependency, hepsi küçük parçalar.",{"type":32,"tag":78,"props":367,"children":368},{},[369,374],{"type":32,"tag":82,"props":370,"children":371},{},[372],{"type":37,"value":373},"Draft PR:",{"type":37,"value":375}," Henüz bitmedi ama mimari görüş istiyorsan draft aç. Review'dan sayılmaz, informal feedback.",{"type":32,"tag":33,"props":377,"children":378},{},[379,384],{"type":32,"tag":82,"props":380,"children":381},{},[382],{"type":37,"value":383},"Comment density:",{"type":37,"value":385}," PR başına ortalama 2-4 yorum ideal. 0 yorum: ya trivial değişiklik ya da reviewer bakmamış. 8+ yorum: scope kaymış veya standart belirsiz.",{"type":32,"tag":40,"props":387,"children":389},{"id":388},"ölçülebilir-kalite-metrikleri-review-dashboard",[390],{"type":37,"value":391},"Ölçülebilir kalite metrikleri: review dashboard",{"type":32,"tag":33,"props":393,"children":394},{},[395],{"type":37,"value":396},"Review kültürü veriyle yönetilir. Roibase'de şu metrikler haftalık dashboard'da:",{"type":32,"tag":74,"props":398,"children":399},{},[400,410,420,430],{"type":32,"tag":78,"props":401,"children":402},{},[403,408],{"type":32,"tag":82,"props":404,"children":405},{},[406],{"type":37,"value":407},"Median time-to-review:",{"type":37,"value":409}," ekip ortalaması, kişisel outlier'lar görünür",{"type":32,"tag":78,"props":411,"children":412},{},[413,418],{"type":32,"tag":82,"props":414,"children":415},{},[416],{"type":37,"value":417},"Approval rate first round:",{"type":37,"value":419}," ilk review'da approve oranı (hedef >60%)",{"type":32,"tag":78,"props":421,"children":422},{},[423,428],{"type":32,"tag":82,"props":424,"children":425},{},[426],{"type":37,"value":427},"Comment type breakdown:",{"type":37,"value":429}," nit-pick (%20 altı), bug (%30+), mimari tartışma (%50 civarı)",{"type":32,"tag":78,"props":431,"children":432},{},[433,438],{"type":32,"tag":82,"props":434,"children":435},{},[436],{"type":37,"value":437},"Blocked PR count:",{"type":37,"value":439}," 24 saat+ bekleyen PR sayısı (hedef 0)",{"type":32,"tag":33,"props":441,"children":442},{},[443],{"type":37,"value":444},"Bu dashboard'u Linear\u002FJira üzerinden değil, GitHub API + custom script ile çekin. Örnek:",{"type":32,"tag":446,"props":447,"children":451},"pre",{"code":448,"language":449,"meta":16,"className":450,"style":16},"# Basitleştirilmiş örnek — production'da GitHub GraphQL API kullan\ndef calculate_review_metrics(repo, start_date):\n    prs = repo.get_pulls(state='closed', sort='updated', direction='desc')\n    \n    metrics = {\n        'time_to_first_review': [],\n        'time_to_merge': [],\n        'comment_density': []\n    }\n    \n    for pr in prs:\n        reviews = pr.get_reviews()\n        if reviews.totalCount > 0:\n            first_review = reviews[0].submitted_at\n            time_diff = (first_review - pr.created_at).total_seconds() \u002F 3600\n            metrics['time_to_first_review'].append(time_diff)\n        \n        if pr.merged:\n            merge_time = (pr.merged_at - pr.created_at).total_seconds() \u002F 3600\n            metrics['time_to_merge'].append(merge_time)\n        \n        metrics['comment_density'].append(pr.comments)\n    \n    return {\n        'median_time_to_review': median(metrics['time_to_first_review']),\n        'median_time_to_merge': median(metrics['time_to_merge']),\n        'avg_comment_density': mean(metrics['comment_density'])\n    }\n","python","language-python shiki shiki-themes github-dark",[452],{"type":32,"tag":52,"props":453,"children":454},{"__ignoreMap":16},[455,467,489,566,575,593,607,620,633,642,650,674,692,722,750,788,807,816,829,863,881,889,908,916,929,952,973,996],{"type":32,"tag":456,"props":457,"children":460},"span",{"class":458,"line":459},"line",1,[461],{"type":32,"tag":456,"props":462,"children":464},{"style":463},"--shiki-default:#6A737D",[465],{"type":37,"value":466},"# Basitleştirilmiş örnek — production'da GitHub GraphQL API kullan\n",{"type":32,"tag":456,"props":468,"children":470},{"class":458,"line":469},2,[471,477,483],{"type":32,"tag":456,"props":472,"children":474},{"style":473},"--shiki-default:#F97583",[475],{"type":37,"value":476},"def",{"type":32,"tag":456,"props":478,"children":480},{"style":479},"--shiki-default:#B392F0",[481],{"type":37,"value":482}," calculate_review_metrics",{"type":32,"tag":456,"props":484,"children":486},{"style":485},"--shiki-default:#E1E4E8",[487],{"type":37,"value":488},"(repo, start_date):\n",{"type":32,"tag":456,"props":490,"children":492},{"class":458,"line":491},3,[493,498,503,508,514,518,524,529,534,538,543,547,552,556,561],{"type":32,"tag":456,"props":494,"children":495},{"style":485},[496],{"type":37,"value":497},"    prs ",{"type":32,"tag":456,"props":499,"children":500},{"style":473},[501],{"type":37,"value":502},"=",{"type":32,"tag":456,"props":504,"children":505},{"style":485},[506],{"type":37,"value":507}," repo.get_pulls(",{"type":32,"tag":456,"props":509,"children":511},{"style":510},"--shiki-default:#FFAB70",[512],{"type":37,"value":513},"state",{"type":32,"tag":456,"props":515,"children":516},{"style":473},[517],{"type":37,"value":502},{"type":32,"tag":456,"props":519,"children":521},{"style":520},"--shiki-default:#9ECBFF",[522],{"type":37,"value":523},"'closed'",{"type":32,"tag":456,"props":525,"children":526},{"style":485},[527],{"type":37,"value":528},", ",{"type":32,"tag":456,"props":530,"children":531},{"style":510},[532],{"type":37,"value":533},"sort",{"type":32,"tag":456,"props":535,"children":536},{"style":473},[537],{"type":37,"value":502},{"type":32,"tag":456,"props":539,"children":540},{"style":520},[541],{"type":37,"value":542},"'updated'",{"type":32,"tag":456,"props":544,"children":545},{"style":485},[546],{"type":37,"value":528},{"type":32,"tag":456,"props":548,"children":549},{"style":510},[550],{"type":37,"value":551},"direction",{"type":32,"tag":456,"props":553,"children":554},{"style":473},[555],{"type":37,"value":502},{"type":32,"tag":456,"props":557,"children":558},{"style":520},[559],{"type":37,"value":560},"'desc'",{"type":32,"tag":456,"props":562,"children":563},{"style":485},[564],{"type":37,"value":565},")\n",{"type":32,"tag":456,"props":567,"children":569},{"class":458,"line":568},4,[570],{"type":32,"tag":456,"props":571,"children":572},{"style":485},[573],{"type":37,"value":574},"    \n",{"type":32,"tag":456,"props":576,"children":578},{"class":458,"line":577},5,[579,584,588],{"type":32,"tag":456,"props":580,"children":581},{"style":485},[582],{"type":37,"value":583},"    metrics ",{"type":32,"tag":456,"props":585,"children":586},{"style":473},[587],{"type":37,"value":502},{"type":32,"tag":456,"props":589,"children":590},{"style":485},[591],{"type":37,"value":592}," {\n",{"type":32,"tag":456,"props":594,"children":596},{"class":458,"line":595},6,[597,602],{"type":32,"tag":456,"props":598,"children":599},{"style":520},[600],{"type":37,"value":601},"        'time_to_first_review'",{"type":32,"tag":456,"props":603,"children":604},{"style":485},[605],{"type":37,"value":606},": [],\n",{"type":32,"tag":456,"props":608,"children":610},{"class":458,"line":609},7,[611,616],{"type":32,"tag":456,"props":612,"children":613},{"style":520},[614],{"type":37,"value":615},"        'time_to_merge'",{"type":32,"tag":456,"props":617,"children":618},{"style":485},[619],{"type":37,"value":606},{"type":32,"tag":456,"props":621,"children":622},{"class":458,"line":26},[623,628],{"type":32,"tag":456,"props":624,"children":625},{"style":520},[626],{"type":37,"value":627},"        'comment_density'",{"type":32,"tag":456,"props":629,"children":630},{"style":485},[631],{"type":37,"value":632},": []\n",{"type":32,"tag":456,"props":634,"children":636},{"class":458,"line":635},9,[637],{"type":32,"tag":456,"props":638,"children":639},{"style":485},[640],{"type":37,"value":641},"    }\n",{"type":32,"tag":456,"props":643,"children":645},{"class":458,"line":644},10,[646],{"type":32,"tag":456,"props":647,"children":648},{"style":485},[649],{"type":37,"value":574},{"type":32,"tag":456,"props":651,"children":653},{"class":458,"line":652},11,[654,659,664,669],{"type":32,"tag":456,"props":655,"children":656},{"style":473},[657],{"type":37,"value":658},"    for",{"type":32,"tag":456,"props":660,"children":661},{"style":485},[662],{"type":37,"value":663}," pr ",{"type":32,"tag":456,"props":665,"children":666},{"style":473},[667],{"type":37,"value":668},"in",{"type":32,"tag":456,"props":670,"children":671},{"style":485},[672],{"type":37,"value":673}," prs:\n",{"type":32,"tag":456,"props":675,"children":677},{"class":458,"line":676},12,[678,683,687],{"type":32,"tag":456,"props":679,"children":680},{"style":485},[681],{"type":37,"value":682},"        reviews ",{"type":32,"tag":456,"props":684,"children":685},{"style":473},[686],{"type":37,"value":502},{"type":32,"tag":456,"props":688,"children":689},{"style":485},[690],{"type":37,"value":691}," pr.get_reviews()\n",{"type":32,"tag":456,"props":693,"children":695},{"class":458,"line":694},13,[696,701,706,711,717],{"type":32,"tag":456,"props":697,"children":698},{"style":473},[699],{"type":37,"value":700},"        if",{"type":32,"tag":456,"props":702,"children":703},{"style":485},[704],{"type":37,"value":705}," reviews.totalCount ",{"type":32,"tag":456,"props":707,"children":708},{"style":473},[709],{"type":37,"value":710},">",{"type":32,"tag":456,"props":712,"children":714},{"style":713},"--shiki-default:#79B8FF",[715],{"type":37,"value":716}," 0",{"type":32,"tag":456,"props":718,"children":719},{"style":485},[720],{"type":37,"value":721},":\n",{"type":32,"tag":456,"props":723,"children":725},{"class":458,"line":724},14,[726,731,735,740,745],{"type":32,"tag":456,"props":727,"children":728},{"style":485},[729],{"type":37,"value":730},"            first_review ",{"type":32,"tag":456,"props":732,"children":733},{"style":473},[734],{"type":37,"value":502},{"type":32,"tag":456,"props":736,"children":737},{"style":485},[738],{"type":37,"value":739}," reviews[",{"type":32,"tag":456,"props":741,"children":742},{"style":713},[743],{"type":37,"value":744},"0",{"type":32,"tag":456,"props":746,"children":747},{"style":485},[748],{"type":37,"value":749},"].submitted_at\n",{"type":32,"tag":456,"props":751,"children":753},{"class":458,"line":752},15,[754,759,763,768,773,778,783],{"type":32,"tag":456,"props":755,"children":756},{"style":485},[757],{"type":37,"value":758},"            time_diff ",{"type":32,"tag":456,"props":760,"children":761},{"style":473},[762],{"type":37,"value":502},{"type":32,"tag":456,"props":764,"children":765},{"style":485},[766],{"type":37,"value":767}," (first_review ",{"type":32,"tag":456,"props":769,"children":770},{"style":473},[771],{"type":37,"value":772},"-",{"type":32,"tag":456,"props":774,"children":775},{"style":485},[776],{"type":37,"value":777}," pr.created_at).total_seconds() ",{"type":32,"tag":456,"props":779,"children":780},{"style":473},[781],{"type":37,"value":782},"\u002F",{"type":32,"tag":456,"props":784,"children":785},{"style":713},[786],{"type":37,"value":787}," 3600\n",{"type":32,"tag":456,"props":789,"children":791},{"class":458,"line":790},16,[792,797,802],{"type":32,"tag":456,"props":793,"children":794},{"style":485},[795],{"type":37,"value":796},"            metrics[",{"type":32,"tag":456,"props":798,"children":799},{"style":520},[800],{"type":37,"value":801},"'time_to_first_review'",{"type":32,"tag":456,"props":803,"children":804},{"style":485},[805],{"type":37,"value":806},"].append(time_diff)\n",{"type":32,"tag":456,"props":808,"children":810},{"class":458,"line":809},17,[811],{"type":32,"tag":456,"props":812,"children":813},{"style":485},[814],{"type":37,"value":815},"        \n",{"type":32,"tag":456,"props":817,"children":819},{"class":458,"line":818},18,[820,824],{"type":32,"tag":456,"props":821,"children":822},{"style":473},[823],{"type":37,"value":700},{"type":32,"tag":456,"props":825,"children":826},{"style":485},[827],{"type":37,"value":828}," pr.merged:\n",{"type":32,"tag":456,"props":830,"children":832},{"class":458,"line":831},19,[833,838,842,847,851,855,859],{"type":32,"tag":456,"props":834,"children":835},{"style":485},[836],{"type":37,"value":837},"            merge_time ",{"type":32,"tag":456,"props":839,"children":840},{"style":473},[841],{"type":37,"value":502},{"type":32,"tag":456,"props":843,"children":844},{"style":485},[845],{"type":37,"value":846}," (pr.merged_at ",{"type":32,"tag":456,"props":848,"children":849},{"style":473},[850],{"type":37,"value":772},{"type":32,"tag":456,"props":852,"children":853},{"style":485},[854],{"type":37,"value":777},{"type":32,"tag":456,"props":856,"children":857},{"style":473},[858],{"type":37,"value":782},{"type":32,"tag":456,"props":860,"children":861},{"style":713},[862],{"type":37,"value":787},{"type":32,"tag":456,"props":864,"children":866},{"class":458,"line":865},20,[867,871,876],{"type":32,"tag":456,"props":868,"children":869},{"style":485},[870],{"type":37,"value":796},{"type":32,"tag":456,"props":872,"children":873},{"style":520},[874],{"type":37,"value":875},"'time_to_merge'",{"type":32,"tag":456,"props":877,"children":878},{"style":485},[879],{"type":37,"value":880},"].append(merge_time)\n",{"type":32,"tag":456,"props":882,"children":884},{"class":458,"line":883},21,[885],{"type":32,"tag":456,"props":886,"children":887},{"style":485},[888],{"type":37,"value":815},{"type":32,"tag":456,"props":890,"children":892},{"class":458,"line":891},22,[893,898,903],{"type":32,"tag":456,"props":894,"children":895},{"style":485},[896],{"type":37,"value":897},"        metrics[",{"type":32,"tag":456,"props":899,"children":900},{"style":520},[901],{"type":37,"value":902},"'comment_density'",{"type":32,"tag":456,"props":904,"children":905},{"style":485},[906],{"type":37,"value":907},"].append(pr.comments)\n",{"type":32,"tag":456,"props":909,"children":911},{"class":458,"line":910},23,[912],{"type":32,"tag":456,"props":913,"children":914},{"style":485},[915],{"type":37,"value":574},{"type":32,"tag":456,"props":917,"children":919},{"class":458,"line":918},24,[920,925],{"type":32,"tag":456,"props":921,"children":922},{"style":473},[923],{"type":37,"value":924},"    return",{"type":32,"tag":456,"props":926,"children":927},{"style":485},[928],{"type":37,"value":592},{"type":32,"tag":456,"props":930,"children":932},{"class":458,"line":931},25,[933,938,943,947],{"type":32,"tag":456,"props":934,"children":935},{"style":520},[936],{"type":37,"value":937},"        'median_time_to_review'",{"type":32,"tag":456,"props":939,"children":940},{"style":485},[941],{"type":37,"value":942},": median(metrics[",{"type":32,"tag":456,"props":944,"children":945},{"style":520},[946],{"type":37,"value":801},{"type":32,"tag":456,"props":948,"children":949},{"style":485},[950],{"type":37,"value":951},"]),\n",{"type":32,"tag":456,"props":953,"children":955},{"class":458,"line":954},26,[956,961,965,969],{"type":32,"tag":456,"props":957,"children":958},{"style":520},[959],{"type":37,"value":960},"        'median_time_to_merge'",{"type":32,"tag":456,"props":962,"children":963},{"style":485},[964],{"type":37,"value":942},{"type":32,"tag":456,"props":966,"children":967},{"style":520},[968],{"type":37,"value":875},{"type":32,"tag":456,"props":970,"children":971},{"style":485},[972],{"type":37,"value":951},{"type":32,"tag":456,"props":974,"children":976},{"class":458,"line":975},27,[977,982,987,991],{"type":32,"tag":456,"props":978,"children":979},{"style":520},[980],{"type":37,"value":981},"        'avg_comment_density'",{"type":32,"tag":456,"props":983,"children":984},{"style":485},[985],{"type":37,"value":986},": mean(metrics[",{"type":32,"tag":456,"props":988,"children":989},{"style":520},[990],{"type":37,"value":902},{"type":32,"tag":456,"props":992,"children":993},{"style":485},[994],{"type":37,"value":995},"])\n",{"type":32,"tag":456,"props":997,"children":999},{"class":458,"line":998},28,[1000],{"type":32,"tag":456,"props":1001,"children":1002},{"style":485},[1003],{"type":37,"value":641},{"type":32,"tag":33,"props":1005,"children":1006},{},[1007],{"type":37,"value":1008},"Dashboard 2 haftada bir retrospective'de açılır. \"Bu sprint median time-to-review 5.2 saat, hedef 4 saat — nerede takıldık?\" sorusu kişisel değil, sistematik tartışma açar.",{"type":32,"tag":40,"props":1010,"children":1012},{"id":1011},"kültür-kuralı-olarak-otomasyonun-sınırları",[1013],{"type":37,"value":1014},"Kültür kuralı olarak otomasyonun sınırları",{"type":32,"tag":33,"props":1016,"children":1017},{},[1018],{"type":37,"value":1019},"Linter ve CI her şeyi halledemez. Mimari kararlar, tradeoff tartışmaları, domain logic review hâlâ insana bağlıdır. Ancak şunu garantileyin: otomasyon \"basit hataları\" önceden yakalasın, insan zamanı \"karmaşık düşünceye\" kalsın.",{"type":32,"tag":33,"props":1021,"children":1022},{},[1023],{"type":32,"tag":82,"props":1024,"children":1025},{},[1026],{"type":37,"value":1027},"Otomasyona verilmesi gerekenler:",{"type":32,"tag":74,"props":1029,"children":1030},{},[1031,1036,1041,1046],{"type":32,"tag":78,"props":1032,"children":1033},{},[1034],{"type":37,"value":1035},"Format check (Prettier, ESLint)",{"type":32,"tag":78,"props":1037,"children":1038},{},[1039],{"type":37,"value":1040},"Type safety (TypeScript strict mode)",{"type":32,"tag":78,"props":1042,"children":1043},{},[1044],{"type":37,"value":1045},"Test coverage (Jest threshold)",{"type":32,"tag":78,"props":1047,"children":1048},{},[1049],{"type":37,"value":1050},"Security scan (Snyk, Dependabot)",{"type":32,"tag":33,"props":1052,"children":1053},{},[1054],{"type":32,"tag":82,"props":1055,"children":1056},{},[1057],{"type":37,"value":1058},"İnsana bırakılması gerekenler:",{"type":32,"tag":74,"props":1060,"children":1061},{},[1062,1067,1072,1077],{"type":32,"tag":78,"props":1063,"children":1064},{},[1065],{"type":37,"value":1066},"API tasarımı tutarlılığı",{"type":32,"tag":78,"props":1068,"children":1069},{},[1070],{"type":37,"value":1071},"Performans tradeoff kararları",{"type":32,"tag":78,"props":1073,"children":1074},{},[1075],{"type":37,"value":1076},"Kullanıcı akışı impact analizi",{"type":32,"tag":78,"props":1078,"children":1079},{},[1080],{"type":37,"value":1081},"Teknik borç kabul\u002Fred",{"type":32,"tag":33,"props":1083,"children":1084},{},[1085],{"type":37,"value":1086},"Ekipte \"linter pass etti ama architecture review fail etti\" durumu normaldir. Ama \"linter fail etti ve PR açıldı\" durumu sistem hatasıdır — pre-commit hook eksiktir.",{"type":32,"tag":40,"props":1088,"children":1090},{"id":1089},"review-yorumlarında-ton-ve-dil-protokolü",[1091],{"type":37,"value":1092},"Review yorumlarında ton ve dil protokolü",{"type":32,"tag":33,"props":1094,"children":1095},{},[1096],{"type":37,"value":1097},"Ölçülebilir kural olsa bile insanlar yorum yazar. Yorum tonunun standardı da olmalı. Roibase'de şu şablon kullanılır:",{"type":32,"tag":33,"props":1099,"children":1100},{},[1101],{"type":32,"tag":82,"props":1102,"children":1103},{},[1104],{"type":37,"value":1105},"Constructive comment şablonu:",{"type":32,"tag":446,"props":1107,"children":1109},{"code":1108},"[Category] Observation\nReasoning: ...\nSuggestion: ... (optional)\nPriority: blocking \u002F non-blocking\n",[1110],{"type":32,"tag":52,"props":1111,"children":1112},{"__ignoreMap":16},[1113],{"type":37,"value":1108},{"type":32,"tag":33,"props":1115,"children":1116},{},[1117],{"type":37,"value":1118},"Örnek:",{"type":32,"tag":446,"props":1120,"children":1122},{"code":1121},"[Performance] Array.find() called in loop (lines 45-52)\nReasoning: O(n²) complexity, 1000+ item array'de 300ms delay\nSuggestion: Convert to Map lookup before loop\nPriority: blocking\n",[1123],{"type":32,"tag":52,"props":1124,"children":1125},{"__ignoreMap":16},[1126],{"type":37,"value":1121},{"type":32,"tag":33,"props":1128,"children":1129},{},[1130],{"type":37,"value":1131},"Bu format \"senin kodun kötü\" yerine \"bu kod şu senaryoda yavaş\" der. Kişiselleştirme yok, odak davranış.",{"type":32,"tag":33,"props":1133,"children":1134},{},[1135,1140],{"type":32,"tag":82,"props":1136,"children":1137},{},[1138],{"type":37,"value":1139},"Non-blocking comment:",{"type":37,"value":1141}," \"Bu çalışır ama gelecekte Y senaryosunda Z sorunu yaşanabilir.\" Merge'i engellemez, teknik borç kaydına girer.",{"type":32,"tag":33,"props":1143,"children":1144},{},[1145,1150],{"type":32,"tag":82,"props":1146,"children":1147},{},[1148],{"type":37,"value":1149},"Blocking comment:",{"type":37,"value":1151}," \"Security issue — user input sanitize edilmemiş.\" Merge edilemez, düzeltme zorunlu.",{"type":32,"tag":33,"props":1153,"children":1154},{},[1155],{"type":37,"value":1156},"Priority tag yoksa default non-blocking kabul edilir. Böylece \"bu PR'ı geçirmeyelim mi?\" tartışması kalkar — blocking tag varsa geçmez, yoksa geçer.",{"type":32,"tag":40,"props":1158,"children":1160},{"id":1159},"kapanış-kişisel-çatışmadan-kurtulmak-için-sayısal-çerçeve",[1161],{"type":37,"value":1162},"Kapanış: kişisel çatışmadan kurtulmak için sayısal çerçeve",{"type":32,"tag":33,"props":1164,"children":1165},{},[1166],{"type":37,"value":1167},"Code review kültürü \"iyi niyet\" üzerine kurulamaz. İyi niyetli ekipler bile subjektif tartışmaya düşer çünkü standart belirsizdir. Çözüm: time-to-review, comment density, PR size gibi metrikleri tanımlayın, otomasyonla enforce edin, dashboard ile takip edin. Bu disiplin sayesinde developer zaman kaybetmez, reviewer keyfi karar vermez, ekip velocity artar. 8+ yıllık ekip liderliği gösterdi ki ölçülemeyen kalite gelişmez — ölçün, optimize edin, tekrarlayın.",{"type":32,"tag":1169,"props":1170,"children":1171},"style",{},[1172],{"type":37,"value":1173},"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":16,"searchDepth":491,"depth":491,"links":1175},[1176,1177,1180,1181,1182,1183,1184],{"id":42,"depth":469,"text":45},{"id":132,"depth":469,"text":135,"children":1178},[1179],{"id":266,"depth":491,"text":269},{"id":277,"depth":469,"text":280},{"id":388,"depth":469,"text":391},{"id":1011,"depth":469,"text":1014},{"id":1089,"depth":469,"text":1092},{"id":1159,"depth":469,"text":1162},"markdown","content:tr:lifestyle:code-review-kulturu-olculebilir-kalite-kisisel-catisma-yok.md","content","tr\u002Flifestyle\u002Fcode-review-kulturu-olculebilir-kalite-kisisel-catisma-yok.md","tr\u002Flifestyle\u002Fcode-review-kulturu-olculebilir-kalite-kisisel-catisma-yok","md",1778709807504]