<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Intertech - Medium]]></title>
        <description><![CDATA[Intertech çalışanları deneyimlerini paylaşıyor - Medium]]></description>
        <link>https://medium.com/intertechit?source=rss----d21876bad59---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Intertech - Medium</title>
            <link>https://medium.com/intertechit?source=rss----d21876bad59---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 16 May 2026 22:27:25 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/intertechit" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Building a Production Chaos Engineering Platform: From Manual Operations to Automated Resilience…]]></title>
            <link>https://medium.com/intertechit/building-a-production-chaos-engineering-platform-from-manual-operations-to-automated-resilience-38c9c6fc96dd?source=rss----d21876bad59---4</link>
            <guid isPermaLink="false">https://medium.com/p/38c9c6fc96dd</guid>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[chaos-engineering]]></category>
            <category><![CDATA[litmuschaos]]></category>
            <category><![CDATA[chaoss]]></category>
            <category><![CDATA[chaos-monkey]]></category>
            <dc:creator><![CDATA[mert polat ☁️ ☸️]]></dc:creator>
            <pubDate>Fri, 17 Apr 2026 07:07:17 GMT</pubDate>
            <atom:updated>2026-04-17T07:07:16.322Z</atom:updated>
            <content:encoded><![CDATA[<h3>Building a Production Chaos Engineering Platform: From Manual Operations to Automated Resilience Testing</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*S1uaflGUnOSrretl1oDM1g.png" /></figure><h3>1. The Problem</h3><h3>The Fintech Reliability Challenge</h3><p>Intertech — the technology subsidiary of DenizBank/Emirates NBD Group and Turkey’s largest fintech company — processes millions of financial transactions daily. A single minute of downtime means regulatory scrutiny, financial loss, and erosion of customer trust.</p><p>Our SRE team’s conviction was clear: <strong>every service must prove it can survive failure before it earns the right to run in production.</strong> But <em>proving</em> resilience systematically across 1000+ microservices was where things broke down.</p><h3>Where Existing Tools Fell Short</h3><p>We adopted LitmusChaos early — a solid chaos experiment engine. But trying to scale it to 1000+ microservices revealed <strong>seven distinct layers of complexity</strong> that no one tool addressed:</p><p><strong>Layer 1 — Experiment Configuration</strong> Write 80+ lines of ChaosEngine YAML per experiment — appinfo, serviceAccount, probes, env vars, labels, annotations.</p><p><strong>Layer 2 — Service Discovery</strong> Manually identify and hardcode applabel, owner team name, SRE team.</p><p><strong>Layer 3 — Health Check Integration</strong> Find the correct readiness probe endpoint and port, compose the probe URL.</p><p><strong>Layer 4 — RBAC Provisioning</strong> Create ServiceAccount + Role + RoleBinding per namespace, per experiment.</p><p><strong>Layer 5 — Safety Enforcement</strong> No mechanism to prevent chaos in kube-system or during low-replica scenarios.</p><p><strong>Layer 6 — Observability</strong> No unified metrics, no dashboards, no correlation between chaos runs and SLO impact.</p><p><strong>Layer 7 — Scheduling &amp; Lifecycle</strong> Every test was a manual trigger — no automation, no recurrence, no central control.</p><p>The result? Only the SRE team ran chaos tests — and even they did it rarely, because each test required 20–30 minutes of YAML authoring and setup. At 1000+ services, chaos engineering was a good idea we couldn’t operationalize. Even with an operator automating the backend, <strong>triggering experiments still required writing YAML and running kubectl</strong> — a barrier that kept chaos engineering locked behind terminal expertise.</p><h3>The Real Cost</h3><p>This wasn’t just a developer experience problem. It was a <strong>resilience coverage gap</strong>:</p><ul><li><strong>~5 services</strong> had ever been chaos-tested (out of 1000+)</li><li><strong>Zero services</strong> had recurring resilience tests</li><li><strong>Zero correlation</strong> between chaos results and production SLOs</li><li><strong>Zero guardrails</strong> — nothing prevented chaos in production-critical system namespaces</li><li><strong>Zero automation</strong> — every test was a one-off, results tracked in Slack messages</li><li><strong>Zero self-service</strong> — QA engineers and developers couldn’t participate without SRE hand-holding</li></ul><h3>2. Our Solution: A Kubernetes Operator That Solves All Seven Layers</h3><p>Instead of solving each layer independently, we built a <strong>single Kubernetes operator</strong> that automates all seven complexity layers behind a declarative CRD — and then topped it with a <strong>browser-based QA Testing Interface</strong> (Section 9) that lets anyone trigger, monitor, and manage chaos experiments without ever opening a terminal.</p><h3>The Core Design Principle</h3><blockquote><strong><em>The user declares intent. The operator handles everything else.</em></strong></blockquote><p>A developer (or SRE) writes this:</p><pre>apiVersion: chaos.platform.io/v1alpha1<br>kind: ChaosExperiment<br>metadata:<br>  name: gateway<br>  namespace: gateway<br>spec:<br>  experiments:<br>    - type: pod-failure<br>    - type: network-loss</pre><p>That’s the <strong>entire input</strong>. No service discovery. No RBAC. No probe URLs. No template authoring. The operator resolves all seven layers automatically.</p><h3>What the Operator Does Behind the Scenes</h3><pre>Developer Input (3 lines of config)<br>         │<br>         ▼<br>┌─────────────────────────────────────────────────────┐<br>│           CHAOS PLATFORM CONTROLLER                  │<br>│                                                      │<br>│  Layer 1 ✓  Experiment Registry → sensible defaults  │<br>│  Layer 2 ✓  Deployment labels → owner, SRE team      │<br>│  Layer 3 ✓  ReadinessProbe → health check URL        │<br>│  Layer 4 ✓  Auto-create SA + Role + RoleBinding      │<br>│  Layer 5 ✓  Kill switch, min replica, forbidden NS   │<br>│  Layer 6 ✓  Prometheus metrics + Grafana dashboards  │<br>│  Layer 7 ✓  Cron schedule + global defaults          │<br>│                                                      │<br>│  Output: Fully configured Litmus ChaosEngine(s)      │<br>└──────────────────────┬──────────────────────────────┘<br>                       ▼<br>              LitmusChaos Engine<br>              → Runner Pod → Experiment → ChaosResult</pre><h3>Why an Operator, Not Scripts or Helm?</h3><p><strong>Helm charts</strong> — Rejected. Still 30+ lines per values file. No runtime intelligence. No reconciliation.</p><p><strong>Shell scripts</strong> — Rejected. No state tracking, no retry, no status reporting, fragile.</p><p><strong>LitmusChaos GameDay API</strong> — Rejected. Good for one-off runs, but no GitOps-friendly CR model, no Kubernetes-native lifecycle.</p><p><strong>Custom Kopf Operator</strong> ✅ — Chosen. Kubernetes-native CRD. Reconciliation loop. Timer handlers. Status management. Leader election. GitOps compatible.</p><h3>3. Expected Efficiency</h3><p>Before building, we calculated the expected return.</p><h3>Per-Service Time Comparison</h3><p>Writing a ChaosEngine YAML by hand used to take <strong>~15 minutes</strong>. The operator auto-generates it.</p><p>Finding service labels and owner info took <strong>~5 minutes</strong> per experiment. The operator auto-discovers from Deployment labels.</p><p>Locating the correct health check endpoint took <strong>~5 minutes</strong>. The operator auto-detects from the readiness probe.</p><p>Creating RBAC resources took <strong>~5 minutes</strong>. The operator auto-provisions ServiceAccount, Role, and RoleBinding idempotently.</p><p>Verifying safety guardrails (namespace allowlist, minimum replica count) took <strong>~3 minutes</strong> of manual review. The operator enforces these automatically.</p><p><strong>Total per experiment: ~33 minutes → ~1 minute</strong> (write a 3-line YAML, apply).</p><h3>Scale Impact</h3><ul><li><strong>Time per experiment setup</strong>: ~33 min → ~1 min — <strong>97% reduction</strong></li><li><strong>Services with chaos coverage</strong>: 5 → 1000+ potential — <strong>200× increase</strong></li><li><strong>Recurring automated tests</strong>: 0 → unlimited (via cron) — <strong>∞</strong></li><li><strong>Manual YAML lines per test</strong>: 80+ → 3<strong>–96% reduction</strong></li><li><strong>RBAC setup per namespace</strong>: manual → automatic — <strong>eliminated</strong></li><li><strong>Safety incidents possible</strong>: yes → no (kill switch + guardrails) — <strong>eliminated</strong></li></ul><h3>4. Implementation</h3><h3>4.1 Architecture</h3><pre>┌─────────────────────────────────────────────────────────────────────────┐<br>│                     KUBERNETES CLUSTER (GKE/Anthos)                     │<br>│                                                                         │<br>│  ┌───────────────────────────────────────────────────────────────────┐  │<br>│  │        CHAOS PLATFORM CONTROLLER (Python 3.13 / Kopf 1.36)        │  │<br>│  │        2 replicas — Leader Election — HA                          │  │<br>│  │                                                                   │  │<br>│  │  on.create/update  →  Reconcile ChaosExperiment CR                │  │<br>│  │  timer(60s)        →  Poll ChaosResults, update status            │  │<br>│  │  timer(60s)        →  Check cron schedule, trigger experiments    │  │<br>│  │  timer(120s)       →  Retry blocked experiments                   │  │<br>│  │  on.delete         →  Cleanup engines, runners, results           │  │<br>│  │  on.resume         →  Re-process Running experiments on restart   │  │<br>│  └───────────────────────────────────────────────────────────────────┘  │<br>│                          │                                              │<br>│           ┌──────────────┼───────────────┐                              │<br>│           ▼              ▼               ▼                              │<br>│  ┌──────────────┐ ┌───────────┐ ┌───────────────┐                       │<br>│  │ LitmusChaos  │ │Prometheus │ │    Kyverno    │                       │<br>│  │ ChaosEngine  │ │ 6 metrics │ │   Policies    │                       │<br>│  │ Runner Pods  │ │ 10 alerts │ │ Forbidden NS  │                       │<br>│  │ ChaosResult  │ │ 2 dashbds │ │Required Labels│                       │<br>│  └──────────────┘ └───────────┘ └───────────────┘                       │<br>└─────────────────────────────────────────────────────────────────────────┘</pre><h3>4.2 The Seven Layers — How Each Is Solved</h3><h4>Layer 1: Experiment Registry — Sensible Defaults</h4><p>Every experiment type maps to a Litmus experiment, a Jinja2 template, and production-tested defaults:</p><pre>EXPERIMENT_REGISTRY = {<br>    &quot;pod-failure&quot;: {<br>        &quot;litmus_name&quot;: &quot;pod-delete&quot;,<br>        &quot;template&quot;: &quot;pod-failure/base.yaml&quot;,<br>        &quot;defaults&quot;: {<br>            &quot;duration&quot;: &quot;60&quot;,<br>            &quot;pods_affected_perc&quot;: &quot;50&quot;,  # Never kill 100% — learned from production<br>            &quot;force&quot;: &quot;false&quot;,<br>        },<br>    },<br>    &quot;network-loss&quot;: {<br>        &quot;litmus_name&quot;: &quot;pod-network-loss&quot;,<br>        &quot;template&quot;: &quot;network-loss/base.yaml&quot;,<br>        &quot;defaults&quot;: {<br>            &quot;duration&quot;: &quot;60&quot;,<br>            &quot;packet_loss_perc&quot;: &quot;30&quot;,<br>            &quot;network_interface&quot;: &quot;eth0&quot;,<br>        },<br>    },<br>    # 6 experiment types total: cpu-stress, memory-stress, pod-failure,<br>    # pod-kill, network-loss, network-failure<br>}</pre><p>The pods_affected_perc: &quot;50&quot; default was a deliberate lesson from production — our first test killed 100% of pods and caused a complete outage. Now half the pods stay alive to serve traffic while the other half are tested.</p><h4>Layer 2: Automatic Service Discovery</h4><p>The operator reads Deployment labels — no user input needed:</p><p>python</p><pre>def detect_service_info(namespace, cr_name):<br>    deployments = apps_api.list_namespaced_deployment(namespace)<br>    target = _find_target_deployment(deployments, cr_name)<br>    labels = target.metadata.labels or {}<br>    return {<br>        &quot;owner&quot;: labels.get(&quot;owner&quot;, &quot;unknown&quot;),<br>        &quot;sre_team&quot;: labels.get(&quot;sreTeamName&quot;, &quot;unknown&quot;),<br>        &quot;app_label&quot;: _detect_app_label(target),  # app= or microServiceName=<br>    }</pre><p>The CR name matches the Deployment name. Owner and SRE team come from standard labels that already exist on every Intertech deployment.</p><h4>Layer 3: Automatic Health Check Detection</h4><p>The operator reads readinessProbe from the target Deployment and constructs the health check URL:</p><pre>def detect_health_check_url(namespace, service_name):<br>    for container in target_deploy.spec.template.spec.containers:<br>        probe = container.readiness_probe or container.liveness_probe<br>        if probe and probe.http_get:<br>            path = probe.http_get.path or &quot;/health&quot;<br>            port = probe.http_get.port or service_port<br>            return f&quot;http://{service_name}.{namespace}.svc.cluster.local:{port}{path}&quot;</pre><p>This URL becomes a continuous HTTP probe during the experiment — if the health check fails, the experiment verdict is Fail.</p><h4>Layer 4: Dynamic RBAC</h4><p>Every target namespace needs a ServiceAccount + Role + RoleBinding for Litmus. The operator creates these idempotently — no manual setup:</p><pre>def ensure_chaos_service_account(namespace):<br>    sa_name = f&quot;{namespace}-chaos-sa&quot;<br>    # Create SA → Role (minimum permissions) → RoleBinding<br>    # All idempotent — safe to call multiple times</pre><h4>Layer 5: Safety Guardrails (Defense in Depth)</h4><p>Five independent safety mechanisms — any one can stop an experiment:</p><ul><li><strong>Kill Switch</strong> — a ConfigMap named chaos-operator-kill-switch. Set enabled: &quot;false&quot; to stop ALL chaos instantly across the cluster.</li><li><strong>Forbidden Namespaces</strong> — kube-system, istio-system, chaosplatform, and others. Hardcoded in the operator and enforced again by a Kyverno policy for defense in depth.</li><li><strong>Min Replica Check</strong> — destructive experiments are blocked if the target Deployment has fewer than 2 replicas.</li><li><strong>Concurrent Limit</strong> — no more than 5 experiments can run simultaneously cluster-wide.</li><li><strong>Phased Execution</strong> — non-destructive tests (cpu-stress, network-loss) run first. Destructive tests (pod-failure, pod-kill) run only after Phase 1 completes.</li></ul><p><strong>Phased Execution</strong> deserves special attention. When a CR has both network-loss and pod-failure:</p><pre>Phase 1 (Non-Destructive)          Phase 2 (Destructive)<br>┌─────────────────────┐            ┌─────────────────────┐<br>│  network-loss       │ ──done──▶  │  pod-failure        │<br>│  cpu-stress         │            │  pod-kill           │<br>└─────────────────────┘            └─────────────────────┘</pre><p>This prevents a scenario where pod-failure kills pods while network-loss is still measuring — giving misleading results.</p><h4>Layer 6: Observability</h4><p>Six Prometheus metrics with owner/SRE team labels for per-team dashboards:</p><ul><li>chaos_experiment_result_total (Counter) — pass/fail results by service, type, and team.</li><li>chaos_engine_status (Gauge) — currently running engines.</li><li>chaos_operator_errors_total (Counter) — operator errors by type.</li><li>chaos_operator_reconcile_queue_length (Gauge) — reconcile backlog.</li><li>chaos_experiment_start_time (Gauge) — experiment start timestamps.</li><li>chaos_policy_violation_total (Counter) — policy violation attempts.</li></ul><p>Plus 10 Prometheus alert rules including <strong>SLO breach correlation</strong> — detecting if error rate exceeds 5% while a chaos experiment is active.</p><h4>Layer 7: Scheduling &amp; Global Defaults</h4><p>The most recent addition — <strong>two-tier cron scheduling</strong>:</p><p><strong>Tier 1 — Operator Global Default:</strong></p><p>yaml</p><pre># Deployment env var — applies to ALL ChaosExperiments<br>env:<br>  - name: DEFAULT_SCHEDULE<br>    value: &quot;0 14 * * 1-5&quot;    # Weekdays at 14:00 UTC<br>  - name: DEFAULT_SUSPEND<br>    value: &quot;false&quot;</pre><p><strong>Tier 2 — Per-CR Override:</strong></p><pre>spec:<br>  schedule: &quot;0 10 * * 1,3&quot;   # This CR: Mon/Wed at 10:00 — overrides global</pre><p><strong>Priority:</strong> CR spec.schedule &gt; Operator DEFAULT_SCHEDULE &gt; None (one-shot)</p><p>This means: set one global cron and every CR automatically becomes a recurring test. Any CR can override with its own schedule or opt out.</p><h3>4.3 Dry-Run Mode</h3><p>Before running real chaos in production, validate the plan:</p><p>yaml</p><pre>spec:<br>  dryRun: true<br>  experiments:<br>    - type: pod-failure<br>    - type: network-loss</pre><p>The operator discovers the service, computes the phased execution plan, and writes everything to status — without creating a single ChaosEngine. Perfect for first-time onboarding.</p><h3>4.4 High Availability</h3><p>The operator runs as 2 replicas with Kopf leader election. Only the leader reconciles — if the leader pod dies, the second pod takes over automatically. Running experiments are re-processed via Kopf’s resume handler.</p><h3>5. Concrete Results</h3><h3>Live Test: gateway/gateway (Network Loss)</h3><p>Our first production test targeted the gateway service in the gateway namespace:</p><pre>1. Applied CR: dryRun=true  → phase: DryRun     ✓ Plan validated<br>2. Applied CR: dryRun=false → phase: Running    ✓ ChaosEngine created<br>3. Runner pod started       → experiment pod    ✓ Network loss injected<br>4. Health probe             → continuous check  ✓ Service stayed healthy<br>5. ChaosResult              → verdict: Pass     ✓ Service survived 30% packet loss<br>6. CR status                → phase: Completed  ✓ lastResult: Success</pre><p><strong>Service proved it can handle 30% network packet loss with zero health check failures.</strong></p><h3>Global Schedule Test</h3><p>Applied a CR <em>without</em> spec.schedule — operator picked up the global DEFAULT_SCHEDULE:</p><pre>1. CR applied (no schedule field)  → Operator used DEFAULT_SCHEDULE=&quot;*/2 * * * *&quot;<br>2. Status                          → phase: Scheduled, nextExecution: 2 min later<br>3. 2 minutes later                 → &quot;Schedule triggered&quot; — experiment ran automatically<br>4. After completion                → Re-scheduled for next window</pre><p><strong>Zero configuration in the CR — fully automated by operator-level defaults.</strong></p><h3>Coverage Impact</h3><ul><li><strong>Services with chaos tests</strong>: 5 → 30+ (growing weekly)</li><li><strong>Recurring scheduled tests</strong>: 0 → all (via global cron)</li><li><strong>Average setup time</strong>: ~33 min → under 1 min</li><li><strong>Manual YAML per test</strong>: 80+ lines → 3 lines</li><li><strong>Safety incidents</strong>: possible → impossible (5-layer guardrails)</li><li><strong>Chaos results in Prometheus</strong>: none → every run, labeled by team</li></ul><h3>6. Adding a New Service — Developer Guide</h3><h3>The Simple Case: Accept All Defaults</h3><p>A developer wants to add chaos testing for their payment-api service in the payments namespace:</p><pre>apiVersion: chaos.platform.io/v1alpha1<br>kind: ChaosExperiment<br>metadata:<br>  name: payment-api        # Must match the Deployment name<br>  namespace: payments      # Target namespace<br>spec:<br>  experiments:<br>    - type: pod-failure</pre><p><strong>That’s it.</strong> Apply with kubectl apply -f and:</p><ul><li>✅ Operator discovers owner and sreTeamName from Deployment labels</li><li>✅ Health check URL auto-detected from readiness probe</li><li>✅ RBAC created automatically in the payments namespace</li><li>✅ Litmus ChaosEngine rendered with production-tested defaults</li><li>✅ Results tracked in Prometheus with team labels</li><li>✅ If global DEFAULT_SCHEDULE is set, it runs on that schedule automatically</li></ul><h3>Multiple Experiment Types</h3><p>yaml</p><pre>spec:<br>  experiments:<br>    - type: pod-failure     # Destructive — runs in Phase 2<br>    - type: network-loss    # Non-destructive — runs in Phase 1<br>    - type: cpu-stress      # Non-destructive — runs in Phase 1</pre><p>Operator automatically separates into phases: network-loss + cpu-stress run first, then pod-failure.</p><h3>Custom Schedule (Override Global)</h3><pre>spec:<br>  schedule: &quot;0 3 * * 6&quot;    # Saturday 03:00 only — overrides global default<br>  experiments:<br>    - type: pod-failure</pre><h3>Validate Before Running (Dry-Run)</h3><pre>spec:<br>  dryRun: true<br>  experiments:<br>    - type: pod-failure<br>    - type: network-loss</pre><p>Check the plan: kubectl get chaosexperiment payment-api -n payments -o yaml → status shows exactly what <em>would</em> happen.</p><h3>Pause Without Deleting</h3><pre>kubectl patch chaosexperiment payment-api -n payments \<br>  -p &#39;{&quot;spec&quot;:{&quot;suspend&quot;:true}}&#39; --type=merge</pre><p>Resume later:</p><pre>kubectl patch chaosexperiment payment-api -n payments \<br>  -p &#39;{&quot;spec&quot;:{&quot;suspend&quot;:false}}&#39; --type=merge</pre><h3>Monitor Results</h3><pre># All experiments at a glance<br>kubectl get chaosexperiments -A<br><br># Output:<br># NS         NAME          SERVICE       PHASE      SCHEDULE         NEXT RUN<br># gateway    gateway       gateway       Scheduled  0 14 * * 1-5     2026-03-31T14:00<br># payments   payment-api   payment-api   Completed                   -</pre><h3>7. Supported Experiment Types</h3><ul><li><strong>pod-failure</strong> — tests pod recovery after graceful deletion. Default impact: 50% of pods, 60 seconds.</li><li><strong>pod-kill</strong> — tests pod recovery after force kill. Default impact: 50% of pods, 60 seconds.</li><li><strong>cpu-stress</strong> — tests behavior under CPU pressure. Default impact: 1 core, 80% load, 60 seconds.</li><li><strong>memory-stress</strong> — tests behavior under memory pressure. Default impact: 128MB allocation, 60 seconds.</li><li><strong>network-loss</strong> — tests resilience to packet loss. Default impact: 30% loss, 60 seconds.</li><li><strong>network-failure</strong> — tests resilience to severe packet loss. Default impact: 50% loss, 60 seconds.</li></ul><h3>8. Operational Commands</h3><p><strong>Stop all chaos (emergency):</strong></p><pre>kubectl -n chaosplatform patch cm chaos-operator-kill-switch \<br>  -p &#39;{&quot;data&quot;:{&quot;enabled&quot;:&quot;false&quot;}}&#39;</pre><p><strong>Resume after emergency:</strong></p><pre>kubectl -n chaosplatform patch cm chaos-operator-kill-switch \<br>  -p &#39;{&quot;data&quot;:{&quot;enabled&quot;:&quot;true&quot;}}&#39;</pre><p><strong>Set global schedule:</strong></p><pre>kubectl -n chaosplatform set env deployment/chaos-operator \<br>  DEFAULT_SCHEDULE=&quot;0 14 * * 1-5&quot;</pre><p><strong>Pause all schedules:</strong></p><pre>kubectl -n chaosplatform set env deployment/chaos-operator \<br>  DEFAULT_SUSPEND=&quot;true&quot;</pre><p><strong>Pause one experiment:</strong></p><pre>kubectl patch chaosexperiment &lt;name&gt; -n &lt;namespace&gt; \<br>  -p &#39;{&quot;spec&quot;:{&quot;suspend&quot;:true}}&#39; --type=merge</pre><p><strong>View operator logs:</strong></p><pre>kubectl -n chaosplatform logs deployment/chaos-operator --tail=50</pre><h3>9. QA Testing Interface — Making Chaos Accessible to Everyone</h3><h3>The Last Mile Problem</h3><p>The operator reduced experiment setup from 33 minutes to 1 minute — but that 1 minute still required:</p><ol><li>SSH or VPN access to the Kubernetes cluster</li><li>kubectl installed and configured</li><li>Knowledge of YAML syntax and CRD schema</li><li>Terminal literacy to check status, read logs, and debug</li></ol><p>For SRE teams, this is fine. For <strong>QA engineers, developers, and product teams</strong> who need to validate resilience before releases, this was still a barrier. We needed a <strong>zero-kubectl, browser-based interface</strong> that runs inside the cluster and speaks directly to the Kubernetes API.</p><h3>Architecture: In-Cluster Real-Time Dashboard</h3><p>The QA UI runs as a first-class Kubernetes workload in the same chaosplatform namespace as the operator. It is not a static dashboard — it is a <strong>live, read-write control plane</strong> for ChaosExperiment custom resources.</p><pre>┌──────────────────────────────────────────────────────────────────────────────┐<br>│                     KUBERNETES CLUSTER                                       │<br>│                                                                              │<br>│  ┌──────────────────────────────────────────┐  ┌──────────────────────────┐  │<br>│  │   CHAOS PLATFORM CONTROLLER (Kopf)       │  │    QA UI Pod             │  │<br>│  │   Reconciles ChaosExperiment CRs         │  │  ┌─────────┐ ┌────────┐  │  │<br>│  │   Creates ChaosEngines                   │◀─│  │ nginx   │ │FastAPI │  │  │<br>│  │   Monitors ChaosResults                  │  │  │ :80     │ │ :8000  │  │  │<br>│  │   Updates CR status                      │  │  │ React   │ │ K8s API│  │  │<br>│  └──────────────────────────────────────────┘  │  │ SPA     │ │ Client │  │  │<br>│              ▲         ▲                       │  └────┬────┘ └───┬────┘  │  │<br>│              │         │                       │       │          │       │  │<br>│     ChaosEngine   ChaosResult                  │       │   REST   │       │  │<br>│              │         │                       │       └────┬─────┘       │  │<br>│              │         │                       │            │             │  │<br>│  ┌───────────┴─────────┴──────┐                │            ▼             │  │<br>│  │      LitmusChaos           │                │   ServiceAccount RBAC    │  │<br>│  │      Runner Pods           │                │   (read deployments,     │  │<br>│  │      Chaos Experiments     │                │    CRUD experiments,     │  │<br>│  └────────────────────────────┘                │    read kill switch)     │  │<br>│                                                └──────────────────────────┘  │<br>│                                                                              │<br>│  ┌──────────────────────────────────────────────────────────────────────────┐│<br>│  │ Ingress: chaos-qa.preprod.internal → QA UI Service :80                  ││<br>│  └──────────────────────────────────────────────────────────────────────────┘│<br>└──────────────────────────────────────────────────────────────────────────────┘</pre><p><strong>Key architectural decisions:</strong></p><ul><li><strong>In-cluster deployment</strong>: The FastAPI backend uses load_incluster_config() — no kubeconfig files, no credentials stored. The Kubernetes API is accessed via the pod&#39;s ServiceAccount token, which is automatically mounted and rotated.</li><li><strong>RBAC-scoped access</strong>: A dedicated ClusterRole grants the UI precisely what it needs — CRUD on chaosexperiments, read-only on deployments and namespaces, and read access to the kill switch ConfigMap. Nothing more.</li><li><strong>Two-container pod</strong>: nginx serves the React SPA on port 80 and reverse-proxies /api/* to the FastAPI backend on port 8000. No CORS issues in production. One pod, one service, one ingress.</li><li><strong>SQLite for history</strong>: Experiment history is persisted to a PVC-backed SQLite database, providing durability across pod restarts without requiring an external database dependency.</li></ul><h3>What the UI Can Do — Full Lifecycle from a Browser</h3><p>Every operation that was previously a kubectl command is now a button click:</p><ul><li><strong>List allowed namespaces</strong> — kubectl get ns becomes a namespace dropdown auto-filtered to the allowed list.</li><li><strong>List deployments</strong> — kubectl get deploy -n gateway becomes a deployment dropdown that shows live replica status.</li><li><strong>Create experiment</strong> — kubectl apply -f experiment.yaml becomes &quot;select types → click Run Experiment&quot;.</li><li><strong>Delete experiment</strong> — kubectl delete chaosexperiment gateway -n gateway becomes a Delete button on the experiment card.</li><li><strong>View experiment status</strong> — kubectl get chaosexperiment -o yaml becomes a real-time dashboard with phase badges.</li><li><strong>Suspend schedule</strong> — kubectl patch ... suspend=true becomes a Suspend button.</li><li><strong>Emergency stop</strong> — the kill-switch patch becomes a kill switch indicator in the header.</li><li><strong>View experiment history</strong> — grepping Prometheus or logs becomes a searchable history table with filters and CSV export.</li></ul><h3>Real-Time Kubernetes Interaction</h3><p>The UI is not a static page that refreshes on demand. It maintains <strong>continuous real-time awareness</strong> of the cluster state:</p><ol><li><strong>10-second auto-refresh</strong>: The frontend polls all active experiments, stats, and kill switch status every 10 seconds. A spinning indicator shows when a refresh cycle is in progress.</li><li><strong>Live countdown timers</strong>: When an experiment is in the Running phase, the dashboard shows a live elapsed-time counter that ticks every second — giving immediate visual feedback that something is happening in the cluster.</li><li><strong>Phase transition tracking</strong>: As the operator reconciles a ChaosExperiment through its lifecycle (Pending → Running → Completed), the UI reflects each transition in real time with color-coded phase badges.</li><li><strong>Instant deployment discovery</strong>: When a QA engineer selects a namespace, the backend queries the Kubernetes API in real time to list deployments with their current replica count. This is not cached — it reflects the live cluster state, so a recently scaled deployment appears immediately.</li></ol><h3>Creating an Experiment — Zero YAML, Full Power</h3><p>Here is what a QA engineer sees when creating an experiment through the UI:</p><p><strong>Step 1 — Select Target:</strong></p><ul><li>Choose namespace from a filtered dropdown (only allowed namespaces appear)</li><li>Choose deployment from a live-queried list (shows ready/total replica count)</li><li>Pin frequently used deployments for one-click access</li></ul><p><strong>Step 2 — Select Experiment Types:</strong></p><ul><li>Six experiment type cards with descriptions and destructive/non-destructive badges</li><li>Multiple selection — the operator handles phased execution automatically</li><li>Phase indicators show which experiments run in Phase 1 vs Phase 2</li></ul><p><strong>Step 3 — Configure Options:</strong></p><ul><li><strong>Dry Run toggle</strong>: Validate the execution plan without creating any ChaosEngine</li><li><strong>Schedule builder</strong>: Visual cron builder with presets (weekdays, daily, weekly) or custom cron input — shows human-readable preview (“Every weekday at 14:00 UTC”)</li><li><strong>Tags</strong>: Categorize experiments (sprint-42, team-sre, regression)</li></ul><p><strong>Step 4 — Review Execution Plan:</strong> A live sidebar shows exactly what will happen:</p><ul><li>Target deployment</li><li>Phase 1 experiments (non-destructive)</li><li>Phase 2 experiments (destructive)</li><li>Safety guardrails that will be enforced</li><li>Mode badges (DRY RUN, SCHEDULED, DESTRUCTIVE)</li></ul><p><strong>Step 5 — Confirm and Run:</strong></p><ul><li>Non-destructive experiments run immediately on click</li><li>Destructive experiments trigger a confirmation modal with red warnings</li><li>The backend POSTs to /api/experiments, which calls the Kubernetes API to create the ChaosExperiment CR</li><li>The operator picks it up within seconds and begins reconciliation</li><li>The UI auto-navigates to the Dashboard where the experiment appears in real time</li></ul><h3>The Confirmation Safety Net</h3><p>When a QA engineer selects destructive experiment types (pod-failure, pod-kill) without dry-run mode, the UI presents a <strong>mandatory confirmation modal</strong>:</p><pre>⚠️ Destructive Experiment<br><br>You are about to run destructive chaos experiments on<br>gateway/gateway. This will affect live pods.<br>┌─────────────────────────────────┐<br>│ 💥 Pod Failure                  │<br>│ ☠️ Pod Kill                     │<br>└─────────────────────────────────┘<br>[Cancel]        [Confirm &amp; Run]</pre><p>This is a deliberate UX decision — the UI should make safe things easy and dangerous things deliberate. Combined with the operator’s five-layer guardrails, it becomes extremely difficult to cause unintended damage.</p><h3>Dashboard — Live Cluster State</h3><p>The Dashboard view provides a real-time overview of all experiments across all allowed namespaces:</p><ul><li><strong>Stats bar</strong>: Active / Passed / Failed / Scheduled / Total — updated every 10 seconds from Kubernetes</li><li><strong>Experiment cards</strong>: Each card shows the experiment name, namespace, phase badge (color-coded and animated for Running), experiment types, creation time, and schedule</li><li><strong>Phase filters</strong>: Toggle between All / Active / Completed / Scheduled views</li><li><strong>Global search</strong>: Filter experiments by name, namespace, or experiment type across the entire cluster</li><li><strong>Live countdown</strong>: Running experiments show elapsed time with a pulsing animation</li><li><strong>Detail modal</strong>: Click any experiment card to see full status history, including every phase transition the operator recorded in the CR status</li></ul><h3>History &amp; Reporting</h3><p>Every experiment triggered through the UI is recorded in a SQLite database with full metadata — namespace and deployment from the user selection, experiment types from the user selection, phase and result polled from the Kubernetes API, the cron schedule expression, start timestamps and duration, and the trigger source (always “qa-ui” for UI-initiated experiments).</p><p>This data powers:</p><ul><li><strong>14-day timeline chart</strong>: Bar chart showing daily experiment activity with success/failure breakdown</li><li><strong>Success rate widget</strong>: SVG ring chart showing overall pass rate with per-namespace breakdown</li><li><strong>HTML report generator</strong>: One-click downloadable report with stats, charts, and full experiment table</li><li><strong>CSV export</strong>: Raw data export for further analysis in Excel or BI tools</li></ul><h3>Topology View — Cluster-Wide Visibility</h3><p>The Topology view shows a grid of all allowed namespaces as interactive cards:</p><ul><li>Each card displays the namespace name, deployment count, and active/completed/failed experiment counts</li><li>Color-coded status indicators: green (healthy), amber with pulse animation (experiments running), red (failures)</li><li>Click any namespace to expand and see all experiments in that namespace with phase badges</li></ul><p>This gives leadership and SRE managers a <strong>single-screen view</strong> of chaos engineering coverage across the entire organization.</p><h3>Templates &amp; Quick Actions — Accelerating Repetitive Work</h3><p>QA teams often run the same experiments repeatedly — the UI makes this frictionless:</p><ul><li><strong>Save as Template</strong>: After configuring an experiment, click “Save Template” to store the full configuration (namespace, deployment, types, schedule, tags) in localStorage</li><li><strong>Template Gallery</strong>: Browse saved templates, rename, delete, or instantly load them into the trigger form</li><li><strong>Quick Re-run</strong>: The last 6 experiments are shown as one-click cards on the trigger page</li><li><strong>Pinned Deployments</strong>: Star frequently tested deployments for instant access across sessions</li></ul><h3>Bulk Operations — Enterprise Scale</h3><p>For organization-wide resilience campaigns (e.g., pre-release regression), the Bulk Operations modal allows:</p><ol><li>Select multiple namespaces at once</li><li>Select experiment types</li><li>Choose dry-run mode (recommended for bulk)</li><li>One click creates experiments across all selected namespaces</li></ol><p>The UI reports: <em>“Bulk: 12 experiments created, 0 failed”</em> — each experiment then follows the normal operator reconciliation lifecycle.</p><h3>Dark/Light Theme &amp; Accessibility</h3><p>The UI ships with both themes, persisted in localStorage:</p><ul><li><strong>Enterprise White</strong> (default): Clean #F8F9FB background, #1E3A5F brand navy, designed for corporate environments and projector presentations</li><li><strong>Dark Mode</strong>: #0F1117 background, #60A5FA accent blue, optimized for extended monitoring sessions and SRE war rooms</li></ul><p>Toggle with the 🌙/☀️ button in the header or the T keyboard shortcut.</p><h3>Keyboard Shortcuts — Power User Workflow</h3><p>For SRE engineers who prefer keyboard-driven workflows:</p><ul><li>1 – 5 — switch tabs (Trigger → Dashboard → History → Templates → Topology)</li><li>/ or Ctrl+K — focus the search bar</li><li>R — refresh all data from Kubernetes</li><li>N — jump to New Experiment (Trigger tab)</li><li>B — open Bulk Operations</li><li>T — toggle theme</li><li>? — show shortcut help</li><li>Escape — close modals or clear search</li></ul><p>All shortcuts are disabled when focus is in an input field.</p><h3>Mobile Responsive Design</h3><p>The UI adapts to mobile screens for on-the-go monitoring:</p><ul><li>Header navigation becomes horizontally scrollable</li><li>Stats bar stacks from 5 columns to 2 columns (tablet) to 1 column (phone)</li><li>Experiment cards stack vertically</li><li>Modals stretch to full width</li><li>Touch-friendly button sizes throughout</li></ul><h3>Deployment Model</h3><p>The QA UI is deployed as a Kubernetes-native workload:</p><p>yaml</p><pre># Single Pod — 2 containers<br>containers:<br>  - name: frontend     # nginx → React SPA on :80<br>    image: &lt;internal-registry&gt;/chaosplatform/qa-ui-frontend:latest<br>  - name: backend      # FastAPI → K8s API client on :8000<br>    image: &lt;internal-registry&gt;/chaosplatform/qa-ui-backend:latest<br>    env:<br>      - name: K8S_IN_CLUSTER<br>        value: &quot;true&quot;<br>      - name: ALLOWED_NAMESPACES<br>        value: &quot;gateway,payments,fraud,identity,lending,notifications,insurance&quot;</pre><pre># RBAC<br>ClusterRole: chaosexperiments CRUD, deployments read, configmaps read<br>ServiceAccount: chaos-qa-ui-sa (namespace: chaosplatform)</pre><pre># Storage<br>PVC: 1Gi for SQLite experiment history</pre><pre># Access<br>Ingress: chaos-qa.preprod.internal</pre><p>All container images are built from an internal private registry and pass the standard security pipeline — SAST/SCA analysis, container vulnerability scanning, and image signing — before deployment.</p><h3>The Impact: From kubectl to Self-Service</h3><ul><li><strong>Who can run chaos experiments</strong>: SRE team only (kubectl) → any QA engineer, developer, or manager</li><li><strong>Knowledge required</strong>: YAML, CRD schema, kubectl, K8s auth → open browser, click buttons</li><li><strong>Time to trigger an experiment</strong>: ~1 min (with operator) → ~10 seconds (select, click, done)</li><li><strong>Time to understand cluster state</strong>: kubectl get + parse YAML output → glance at dashboard</li><li><strong>Experiment history</strong>: grep Prometheus or operator logs → searchable table + timeline + reports</li><li><strong>Organization-wide coverage view</strong>: custom Grafana dashboard → built-in Topology view</li><li><strong>Bulk testing for releases</strong>: script loops with kubectl → one-click Bulk Operations</li><li><strong>Recurring test configuration</strong>: edit YAML, re-apply CR → visual schedule builder</li></ul><p>The QA UI transforms chaos engineering from an <strong>SRE-gated, terminal-only activity</strong> into a <strong>self-service capability</strong> available to the entire engineering organization.</p><h3>10. Technology Stack</h3><ul><li><strong>Operator Runtime</strong> — Python 3.13 + Kopf 1.36 for CRD reconciliation, timer handlers, and leader election.</li><li><strong>Template Engine</strong> — Jinja2 3.1 for ChaosEngine YAML rendering.</li><li><strong>Schedule Engine</strong> — croniter 6.2 for cron expression parsing.</li><li><strong>CRD</strong> — chaos.platform.io/v1alpha1 ChaosExperiment custom resource.</li><li><strong>Experiment Engine</strong> — LitmusChaos 3.9 (go-runner, chaos-runner, ChaosResult).</li><li><strong>Policy Enforcement</strong> — Kyverno for forbidden namespaces and required labels.</li><li><strong>Observability</strong> — Prometheus + Grafana with 6 metrics, 10 alerts, and 2 dashboards.</li><li><strong>QA UI Frontend</strong> — React 18 + Tailwind CSS v4 (CDN) as a single-file SPA, no build step required.</li><li><strong>QA UI Backend</strong> — Python 3.13 + FastAPI 0.115 with a Kubernetes API client, SQLite history, and a REST API.</li><li><strong>QA UI Proxy</strong> — nginx for static file serving and reverse proxy to the backend.</li><li><strong>QA UI History</strong> — SQLite for experiment history, stats, and CSV/HTML reports.</li><li><strong>Container Registry</strong> — internal private registry for enterprise-grade artifact storage.</li><li><strong>CI/CD</strong> — Jenkins with SAST/SCA analysis, container vulnerability scanning, and image signing for build, scan, sign, and deploy.</li><li><strong>HA</strong> — 2 replicas + Kopf peering for leader election and automatic failover.</li></ul><h3>11. Key Takeaways</h3><ol><li><strong>The value isn’t writing less YAML — it’s eliminating seven layers of operational complexity.</strong> Every layer we automated (discovery, RBAC, health checks, safety, scheduling, observability, lifecycle) is a layer that can no longer be forgotten, misconfigured, or skipped.</li><li><strong>Guardrails enable adoption.</strong> Teams started using chaos testing when they knew it <em>couldn’t</em> accidentally hit kube-system or kill all replicas. Safety made trust possible.</li><li><strong>Global defaults with local overrides is the right abstraction.</strong> One cron expression at the operator level gives every service recurring tests. Any team can override for their own needs. Zero coordination required.</li><li><strong>Your first test will fail — and that’s the point.</strong> Our first pod-failure test killed 100% of pods and proved the service had zero graceful degradation. That finding alone justified the entire project.</li><li><strong>A platform is not complete until non-experts can use it.</strong> The operator solved the complexity problem for SRE engineers. The QA UI solved the accessibility problem for everyone else. When a QA engineer can trigger, monitor, and report on chaos experiments from a browser without writing a single line of YAML or touching kubectl, chaos engineering stops being an SRE discipline and becomes an organizational capability.</li></ol><p><em>Mert Polat is an Expert SRE at Intertech (DenizBank / Emirates NBD Group) and the LitmusChaos Turkey Community Lead. He initiated the chaos engineering effort within the organization, working in close collaboration with Architect SRE Buğra Çakmak, who designed the system architecture, and under the leadership of their manager Salih Eligüzel, who championed and enabled the initiative.</em></p><p><em>Together, they built a production-grade chaos engineering platform that proves services can survive failure — from Kubernetes operators that automate resilience testing to browser-based interfaces that make chaos engineering accessible to the entire organization.</em></p><p><em>Intertech is listed as an official LitmusChaos adopter at litmuschaos.io</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=38c9c6fc96dd" width="1" height="1" alt=""><hr><p><a href="https://medium.com/intertechit/building-a-production-chaos-engineering-platform-from-manual-operations-to-automated-resilience-38c9c6fc96dd">Building a Production Chaos Engineering Platform: From Manual Operations to Automated Resilience…</a> was originally published in <a href="https://medium.com/intertechit">Intertech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Production’da Chaos Engineering Platformu: Manuel İşlerden Oto. Dayanıklılık Testine]]></title>
            <link>https://medium.com/intertechit/productionda-chaos-engineering-platformu-manuel-i%CC%87%C5%9Flerden-oto-dayan%C4%B1kl%C4%B1l%C4%B1k-testine-2804f704144a?source=rss----d21876bad59---4</link>
            <guid isPermaLink="false">https://medium.com/p/2804f704144a</guid>
            <category><![CDATA[chaos-engineering]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[chaoss]]></category>
            <category><![CDATA[chaos-monkey]]></category>
            <category><![CDATA[litmuschaos]]></category>
            <dc:creator><![CDATA[mert polat ☁️ ☸️]]></dc:creator>
            <pubDate>Fri, 17 Apr 2026 07:06:47 GMT</pubDate>
            <atom:updated>2026-04-17T07:06:46.080Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Z10Gyv_324QwSa6-u9coUw.png" /></figure><h3>1. Problem</h3><h3>Fintech’te Kesinti Lüksün Yok</h3><p>Intertech, DenizBank/Emirates NBD grubunun teknoloji şirketi — Türkiye’nin en büyük fintech’i. Her gün milyonlarca finansal işlem. Bir dakika kesinti? Regülatör soruşturması, para kaybı, müşteri güveni gitti.</p><p>SRE olarak tek bir prensibimiz vardı: <strong>production’a çıkmak isteyen servis, önce bize dayanıklılığını kanıtlayacak.</strong> Kulağa hoş geliyor. Ama 1000+ mikroservis varken bunu nasıl sistematik yapacaksın? İşte asıl problem buydu.</p><h3>Mevcut Araçlar Neden Yetmedi?</h3><p>LitmusChaos’u erkenden aldık — sağlam bir chaos engine. Ama 1000+ servise ölçeklemeye çalışınca, tek bir aracın çözemeyeceği <strong>yedi farklı karmaşıklık katmanı</strong> çıktı karşımıza:</p><p><strong>Katman 1 — Experiment Config</strong> Her test için 80+ satır ChaosEngine YAML yaz (appinfo, serviceAccount, probe, env var, label, annotation).</p><p><strong>Katman 2 — Service Discovery</strong> applabel, owner, SRE team bilgisini bul, elle yaz.</p><p><strong>Katman 3 — Health Check</strong> Doğru readiness probe endpoint’ini bul, URL’i oluştur.</p><p><strong>Katman 4 — RBAC</strong> Her namespace için ServiceAccount + Role + RoleBinding oluştur.</p><p><strong>Katman 5 — Güvenlik</strong> kube-system&#39;de veya düşük replica senaryolarında chaos çalışmasını engelleyecek bir mekanizma yok.</p><p><strong>Katman 6 — Observability</strong> Birleşik metrik yok, dashboard yok, chaos run’larıyla SLO etkisi arasında korelasyon yok.</p><p><strong>Katman 7 — Scheduling</strong> Her test manuel tetikleniyor — otomasyon yok, tekrar yok, merkezi kontrol yok.</p><p>Sonuç mu? Chaos testi sadece SRE yapıyordu — o da ayda bir, şansımız yaver giderse. Her test 20–30 dakika YAML yazmak demekti. 1000+ serviste chaos engineering? Güzel bir fikirdi, hayata geçiremedik.</p><h3>Gerçek Maliyet</h3><p>Bu sadece developer experience problemi değildi. <strong>Dayanıklılık coverage’ı sıfıra yakındı:</strong></p><ul><li>1000+ servisten sadece <strong>~5 tanesi</strong> chaos testi görmüştü</li><li>Recurring test yapan servis sayısı: <strong>sıfır</strong></li><li>Chaos sonuçları ile production SLO’lar arasında korelasyon: <strong>sıfır</strong></li><li>kube-system gibi kritik namespace&#39;leri koruyan guardrail: <strong>sıfır</strong></li><li>Her test one-off, sonuçlar Slack’te bir yerde kayboluyordu</li><li>QA mühendisleri veya developer’lar katılamıyordu — SRE el tutmadan olmuyor</li></ul><h3>2. Çözüm: Yedi Katmanı Tek Operatörle Çözmek</h3><p>Her katmanı ayrı ayrı çözmek yerine, <strong>tek bir Kubernetes operatörü</strong> yazdım. Yedi katmanın hepsini deklaratif bir CRD arkasında otomatikleştiriyor. Üstüne bir de <strong>browser-based QA arayüzü</strong> ekledik — artık kimse terminal açmadan chaos test yapabiliyor.</p><h3>Temel Prensip</h3><blockquote><strong><em>Kullanıcı ne istediğini söyler. Operatör gerisini halleder.</em></strong></blockquote><p>Bir developer şunu yazıyor:</p><pre>apiVersion: chaos.platform.io/v1alpha1<br>kind: ChaosExperiment<br>metadata:<br>  name: gateway<br>  namespace: gateway<br>spec:<br>  experiments:<br>    - type: pod-failure<br>    - type: network-loss</pre><p><strong>Bu kadar.</strong> Service discovery yok. RBAC yok. Probe URL yok. Template yok. Operatör yedi katmanı otomatik çözüyor.</p><h3>Arka Planda Ne Oluyor?</h3><pre>Developer Input (3 satır config)<br>         │<br>         ▼<br>┌─────────────────────────────────────────────────────┐<br>│         CHAOS PLATFORM CONTROLLER                    │<br>│                                                      │<br>│  Katman 1 ✓  Experiment Registry → akıllı default&#39;lar│<br>│  Katman 2 ✓  Deployment label&#39;ları → owner, SRE team │<br>│  Katman 3 ✓  ReadinessProbe → health check URL       │<br>│  Katman 4 ✓  Auto SA + Role + RoleBinding            │<br>│  Katman 5 ✓  Kill switch, min replica, forbidden NS  │<br>│  Katman 6 ✓  Prometheus metrics + Grafana            │<br>│  Katman 7 ✓  Cron scheduling + global default&#39;lar    │<br>│                                                      │<br>│  Output: Tam configure edilmiş Litmus ChaosEngine    │<br>└──────────────────────┬──────────────────────────────┘<br>                       ▼<br>              LitmusChaos Engine<br>              → Runner Pod → Experiment → ChaosResult</pre><h3>Neden Operatör? Neden Script veya Helm Değil?</h3><p><strong>Helm charts</strong> — Olmadı. Yine 30+ satır values file. Runtime intelligence yok. Reconciliation yok.</p><p><strong>Shell scripts</strong> — Olmadı. State tracking yok, retry yok, status reporting yok. Kırılgan.</p><p><strong>LitmusChaos GameDay API</strong> — Olmadı. One-off run’lar için tamam, ama GitOps-friendly CR modeli yok, Kubernetes-native lifecycle yok.</p><p><strong>Custom Kopf Operatörü</strong> ✅ — Seçildi. Kubernetes-native CRD. Reconciliation loop. Timer handler. Status management. Leader election. GitOps uyumlu.</p><h3>3. Beklenen Kazanım</h3><p>Build etmeden önce hesabı yaptık.</p><h3>Servis Başına Süre Karşılaştırması</h3><p>ChaosEngine YAML’ı elle yazmak <strong>~15 dakika</strong> sürüyordu. Operatör otomatik üretiyor.</p><p>Service label ve owner bilgisini bulmak her experiment’ta <strong>~5 dakika</strong> alıyordu. Operatör Deployment label’larından otomatik discover ediyor.</p><p>Doğru health check endpoint’ini bulmak <strong>~5 dakika</strong> sürüyordu. Operatör readiness probe’dan otomatik detect ediyor.</p><p>RBAC resource’larını oluşturmak <strong>~5 dakika</strong> sürüyordu. Operatör ServiceAccount, Role ve RoleBinding’i idempotent olarak auto-provision ediyor.</p><p>Güvenlik kontrolleri (namespace allowlist, minimum replica) manuel review’da <strong>~3 dakika</strong> alıyordu. Operatör otomatik enforce ediyor.</p><p><strong>Toplam: ~33 dakika → ~1 dakika</strong> (3 satır YAML yaz, apply et).</p><h3>Ölçek Etkisi</h3><ul><li><strong>Experiment başına setup süresi</strong>: ~33 dk → ~1 dk — <strong>%97 azalma</strong></li><li><strong>Chaos coverage olan servis</strong>: 5 → 1000+ potansiyel — <strong>200× artış</strong></li><li><strong>Recurring otomatik test</strong>: 0 → sınırsız (cron ile) — <strong>∞</strong></li><li><strong>Test başına manuel YAML satırı</strong>: 80+ → 3 — <strong>%96 azalma</strong></li><li><strong>Namespace başına RBAC setup</strong>: manuel → otomatik — <strong>ortadan kalktı</strong></li><li><strong>Olası güvenlik incident’ı</strong>: var → yok (kill switch + guardrail’ler) — <strong>ortadan kalktı</strong></li></ul><h3>4. İmplementasyon</h3><h3>4.1 Mimari</h3><pre>┌─────────────────────────────────────────────────────────────────────────┐<br>│                     KUBERNETES CLUSTER (GKE/Anthos)                     │<br>│                                                                         │<br>│  ┌───────────────────────────────────────────────────────────────────┐  │<br>│  │        CHAOS PLATFORM CONTROLLER (Python 3.13 / Kopf 1.36)        │  │<br>│  │        2 replica — Leader Election — HA                           │  │<br>│  │                                                                   │  │<br>│  │  on.create/update  →  ChaosExperiment CR reconcile                │  │<br>│  │  timer(60s)        →  ChaosResult poll, status update             │  │<br>│  │  timer(60s)        →  Cron schedule check, experiment trigger     │  │<br>│  │  timer(120s)       →  Blocked experiment retry                    │  │<br>│  │  on.delete         →  Engine, runner, result cleanup              │  │<br>│  │  on.resume         →  Restart sonrası Running experiment devralma │  │<br>│  └───────────────────────────────────────────────────────────────────┘  │<br>│                          │                                              │<br>│           ┌──────────────┼───────────────┐                              │<br>│           ▼              ▼               ▼                              │<br>│  ┌──────────────┐ ┌───────────┐ ┌───────────────┐                       │<br>│  │ LitmusChaos  │ │Prometheus │ │    Kyverno    │                       │<br>│  │ ChaosEngine  │ │ 6 metrik  │ │   Policy&#39;ler  │                       │<br>│  │ Runner Pod   │ │ 10 alert  │ │ Forbidden NS  │                       │<br>│  │ ChaosResult  │ │ 2 dashbrd │ │ Required Label│                       │<br>│  └──────────────┘ └───────────┘ └───────────────┘                       │<br>└─────────────────────────────────────────────────────────────────────────┘</pre><h3>4.2 Yedi Katman — Nasıl Çözüldü?</h3><h4>Katman 1: Experiment Registry — Akıllı Default’lar</h4><p>Her experiment tipi bir Litmus experiment’a, bir Jinja2 template’e ve production’da test edilmiş default’lara map’leniyor:</p><pre>EXPERIMENT_REGISTRY = {<br>    &quot;pod-failure&quot;: {<br>        &quot;litmus_name&quot;: &quot;pod-delete&quot;,<br>        &quot;template&quot;: &quot;pod-failure/base.yaml&quot;,<br>        &quot;defaults&quot;: {<br>            &quot;duration&quot;: &quot;60&quot;,<br>            &quot;pods_affected_perc&quot;: &quot;50&quot;,  # Asla %100 kill etme — acı tecrübe<br>            &quot;force&quot;: &quot;false&quot;,<br>        },<br>    },<br>    &quot;network-loss&quot;: {<br>        &quot;litmus_name&quot;: &quot;pod-network-loss&quot;,<br>        &quot;template&quot;: &quot;network-loss/base.yaml&quot;,<br>        &quot;defaults&quot;: {<br>            &quot;duration&quot;: &quot;60&quot;,<br>            &quot;packet_loss_perc&quot;: &quot;30&quot;,<br>            &quot;network_interface&quot;: &quot;eth0&quot;,<br>        },<br>    },<br>    # Toplam 6 experiment tipi: cpu-stress, memory-stress, pod-failure,<br>    # pod-kill, network-loss, network-failure<br>}</pre><p>pods_affected_perc: &quot;50&quot; default&#39;u acı bir dersin ürünü — ilk testimiz pod&#39;ların %100&#39;ünü öldürdü, servis tamamen gitti. Şimdi yarısı trafik serve ederken diğer yarısı test ediliyor.</p><h4>Katman 2: Otomatik Service Discovery</h4><p>Operatör Deployment label’larını okuyor — user input gerekmiyor:</p><pre>def detect_service_info(namespace, cr_name):<br>    deployments = apps_api.list_namespaced_deployment(namespace)<br>    target = _find_target_deployment(deployments, cr_name)<br>    labels = target.metadata.labels or {}<br>    return {<br>        &quot;owner&quot;: labels.get(&quot;owner&quot;, &quot;unknown&quot;),<br>        &quot;sre_team&quot;: labels.get(&quot;sreTeamName&quot;, &quot;unknown&quot;),<br>        &quot;app_label&quot;: _detect_app_label(target),<br>    }</pre><p>CR adı Deployment adıyla eşleşiyor. Owner ve SRE team zaten her Intertech deployment’ında olan standart label’lardan geliyor.</p><h4>Katman 3: Otomatik Health Check Detection</h4><p>Operatör target Deployment’ın readinessProbe&#39;unu okuyup health check URL&#39;ini oluşturuyor:</p><p>python</p><pre>def detect_health_check_url(namespace, service_name):<br>    for container in target_deploy.spec.template.spec.containers:<br>        probe = container.readiness_probe or container.liveness_probe<br>        if probe and probe.http_get:<br>            path = probe.http_get.path or &quot;/health&quot;<br>            port = probe.http_get.port or service_port<br>            return f&quot;http://{service_name}.{namespace}.svc.cluster.local:{port}{path}&quot;</pre><p>Bu URL experiment süresince continuous HTTP probe olarak çalışıyor — health check fail ederse experiment verdict’i Fail oluyor.</p><h4>Katman 4: Dynamic RBAC</h4><p>Her target namespace için Litmus’un ihtiyacı olan ServiceAccount + Role + RoleBinding operatör tarafından idempotent olarak oluşturuluyor. Manuel setup sıfır.</p><h4>Katman 5: Güvenlik Guardrail’leri (Defense in Depth)</h4><p>Beş bağımsız güvenlik mekanizması — herhangi biri tek başına bir experiment’ı durdurabilir:</p><ul><li><strong>Kill Switch</strong> — chaos-operator-kill-switch adında bir ConfigMap. enabled: &quot;false&quot; yapınca cluster genelindeki TÜM chaos anında duruyor.</li><li><strong>Forbidden Namespace’ler</strong> — kube-system, istio-system, chaosplatform ve diğerleri. Operatörde hardcoded, üstüne Kyverno policy ile defense in depth.</li><li><strong>Min Replica Check</strong> — Target Deployment’ın replica sayısı 2&#39;den azsa destructive experiment’lar blocked.</li><li><strong>Concurrent Limit</strong> — Cluster genelinde aynı anda max 5 experiment çalışabilir.</li><li><strong>Phased Execution</strong> — Non-destructive testler (cpu-stress, network-loss) önce çalışır. Destructive testler (pod-failure, pod-kill) ancak Phase 1 bittikten sonra başlar.</li></ul><p><strong>Phased Execution</strong> özellikle önemli. Bir CR’da hem network-loss hem pod-failure varsa:</p><pre>Phase 1 (Non-Destructive)          Phase 2 (Destructive)<br>┌─────────────────────┐            ┌─────────────────────┐<br>│  network-loss       │ ──bitti──▶ │  pod-failure        │<br>│  cpu-stress         │            │  pod-kill           │<br>└─────────────────────┘            └─────────────────────┘</pre><p>Bu sayede pod-failure pod’ları öldürürken network-loss hâlâ ölçüm yapmaya çalışmıyor — misleading sonuçlar önleniyor.</p><h4>Katman 6: Observability</h4><p>Owner/SRE team label’lı altı Prometheus metric:</p><ul><li>chaos_experiment_result_total (Counter) — servis, tip ve team bazında pass/fail sonuçları.</li><li>chaos_engine_status (Gauge) — şu an running engine sayısı.</li><li>chaos_operator_errors_total (Counter) — operatör error&#39;ları tipe göre.</li><li>chaos_operator_reconcile_queue_length (Gauge) — reconcile backlog.</li><li>chaos_experiment_start_time (Gauge) — experiment start timestamp&#39;leri.</li><li>chaos_policy_violation_total (Counter) — policy violation attempt&#39;leri.</li></ul><p>Üstüne 10 Prometheus alert rule — aralarında <strong>SLO breach correlation</strong> da var: chaos experiment aktifken error rate %5&#39;i geçerse alert tetikleniyor.</p><h4>Katman 7: Scheduling &amp; Global Default’lar</h4><p>En son eklediğimiz feature — <strong>iki kademeli cron scheduling:</strong></p><p><strong>Kademe 1 — Operatör Global Default:</strong></p><pre># Deployment env variable — TÜM ChaosExperiment&#39;lara uygulanıyor<br>env:<br>  - name: DEFAULT_SCHEDULE<br>    value: &quot;0 14 * * 1-5&quot;    # Hafta içi her gün 14:00 UTC<br>  - name: DEFAULT_SUSPEND<br>    value: &quot;false&quot;</pre><p><strong>Kademe 2 — CR Bazında Override:</strong></p><pre>spec:<br>  schedule: &quot;0 10 * * 1,3&quot;   # Bu CR: Pazartesi/Çarşamba 10:00 — global&#39;ı eziyor</pre><p><strong>Öncelik:</strong> CR spec.schedule &gt; Operatör DEFAULT_SCHEDULE &gt; Yok (one-shot)</p><p>Yani: tek bir global cron ayarla, her CR otomatik recurring test haline gelsin. İsteyen CR kendi schedule’ıyla override edebilir.</p><h3>4.3 Dry-Run Mode</h3><p>Production’da gerçek chaos çalıştırmadan önce planı validate et:</p><pre>spec:<br>  dryRun: true<br>  experiments:<br>    - type: pod-failure<br>    - type: network-loss</pre><p>Operatör servisi discover ediyor, phased execution planını hesaplıyor, her şeyi status’a yazıyor — tek bir ChaosEngine oluşturmadan. İlk entegrasyon için ideal.</p><h3>4.4 High Availability</h3><p>Operatör 2 replica ve Kopf leader election ile çalışıyor. Sadece leader reconcile yapıyor — leader pod ölürse ikincisi otomatik devralıyor. Running experiment’lar Kopf’un resume handler’ı ile tekrar işleniyor.</p><h3>5. Somut Sonuçlar</h3><h3>Canlı Test: gateway/gateway (Network Loss)</h3><p>İlk production testimiz gateway namespace&#39;indeki gateway servisini hedef aldı:</p><pre>1. CR apply: dryRun=true   → phase: DryRun    ✓ Plan validate edildi<br>2. CR apply: dryRun=false  → phase: Running   ✓ ChaosEngine oluştu<br>3. Runner pod başladı      → experiment pod   ✓ Network loss inject edildi<br>4. Health probe            → continuous check ✓ Servis sağlıklı kaldı<br>5. ChaosResult             → verdict: Pass    ✓ %30 packet loss&#39;a dayandı<br>6. CR status               → phase: Completed ✓ lastResult: Success</pre><p><strong>Servis %30 network packet loss’u sıfır health check failure ile geçti.</strong></p><h3>Global Schedule Test</h3><p>spec.schedule <strong>olmadan</strong> bir CR apply ettik — operatör global DEFAULT_SCHEDULE&#39;ı aldı:</p><pre>1. CR apply (schedule field yok)  → Operatör DEFAULT_SCHEDULE=&quot;*/2 * * * *&quot; kullandı<br>2. Status                         → phase: Scheduled, nextExecution: 2 dk sonra<br>3. 2 dakika sonra                 → &quot;Schedule tetiklendi&quot; — experiment otomatik çalıştı<br>4. Completion sonrası             → Sonraki window için yeniden schedule edildi</pre><p><strong>CR’da sıfır config — tamamen operatör-level default’larla otomatik.</strong></p><h3>Coverage Etkisi</h3><ul><li><strong>Chaos testi olan servis</strong>: 5 → 30+ (haftalık artıyor)</li><li><strong>Recurring scheduled test</strong>: 0 → hepsi (global cron ile)</li><li><strong>Ortalama setup süresi</strong>: ~33 dk → 1 dakikanın altında</li><li><strong>Test başına manuel YAML</strong>: 80+ satır → 3 satır</li><li><strong>Güvenlik incident’ı</strong>: mümkün → imkansız (5 katman guardrail)</li><li><strong>Prometheus’ta chaos sonuçları</strong>: yok → her run, team label’lı</li></ul><h3>6. Yeni Servis Ekleme — Developer Guide</h3><h3>Basit Case: Tüm Default’ları Kabul Et</h3><p>Bir developer payments namespace&#39;indeki payment-api servisi için chaos testi eklemek istiyor:</p><pre>apiVersion: chaos.platform.io/v1alpha1<br>kind: ChaosExperiment<br>metadata:<br>  name: payment-api        # Deployment adıyla eşleşmeli<br>  namespace: payments      # Target namespace<br>spec:<br>  experiments:<br>    - type: pod-failure</pre><p><strong>Bu kadar.</strong> kubectl apply -f ile uygula:</p><ul><li>✅ Operatör Deployment label’larından owner ve sreTeamName discover ediyor</li><li>✅ Health check URL readiness probe’dan otomatik detect ediliyor</li><li>✅ RBAC payments namespace&#39;inde otomatik oluşturuluyor</li><li>✅ Litmus ChaosEngine production-tested default’larla render ediliyor</li><li>✅ Sonuçlar team label’lı Prometheus metric’lerine gidiyor</li><li>✅ Global DEFAULT_SCHEDULE ayarlıysa o schedule&#39;da otomatik çalışıyor</li></ul><h3>Birden Fazla Experiment Tipi</h3><pre>spec:<br>  experiments:<br>    - type: pod-failure     # Destructive — Phase 2&#39;de çalışır<br>    - type: network-loss    # Non-destructive — Phase 1&#39;de çalışır<br>    - type: cpu-stress      # Non-destructive — Phase 1&#39;de çalışır</pre><p>Operatör otomatik phase’lere ayırıyor: network-loss + cpu-stress önce, sonra pod-failure.</p><h3>Custom Schedule (Global’ı Override Et)</h3><pre>spec:<br>  schedule: &quot;0 3 * * 6&quot;    # Sadece Cumartesi 03:00 — global default&#39;ı eziyor<br>  experiments:<br>    - type: pod-failure</pre><h3>Run Etmeden Validate Et (Dry-Run)</h3><pre>spec:<br>  dryRun: true<br>  experiments:<br>    - type: pod-failure<br>    - type: network-loss</pre><p>Planı kontrol et: kubectl get chaosexperiment payment-api -n payments -o yaml → status&#39;ta ne <em>olacağı</em> görünüyor.</p><h3>Silmeden Pause Et</h3><pre>kubectl patch chaosexperiment payment-api -n payments \<br>  -p &#39;{&quot;spec&quot;:{&quot;suspend&quot;:true}}&#39; --type=merge</pre><p>Resume:</p><pre>kubectl patch chaosexperiment payment-api -n payments \<br>  -p &#39;{&quot;spec&quot;:{&quot;suspend&quot;:false}}&#39; --type=merge</pre><h3>Sonuçları İzle</h3><pre># Tüm experiment&#39;lar bir bakışta<br>kubectl get chaosexperiments -A<br># Output:<br># NS         NAME          SERVICE       PHASE      SCHEDULE         NEXT RUN<br># gateway    gateway       gateway       Scheduled  0 14 * * 1-5     2026-03-31T14:00<br># payments   payment-api   payment-api   Completed                   -</pre><h3>7. Desteklenen Experiment Tipleri</h3><ul><li><strong>pod-failure</strong> — graceful deletion sonrası pod recovery&#39;yi test ediyor. Default impact: pod&#39;ların %50&#39;si, 60 saniye.</li><li><strong>pod-kill</strong> — force kill sonrası pod recovery&#39;yi test ediyor. Default impact: pod&#39;ların %50&#39;si, 60 saniye.</li><li><strong>cpu-stress</strong> — CPU pressure altında davranışı test ediyor. Default impact: 1 core, %80 load, 60 saniye.</li><li><strong>memory-stress</strong> — memory pressure altında davranışı test ediyor. Default impact: 128MB allocation, 60 saniye.</li><li><strong>network-loss</strong> — packet loss&#39;a dayanıklılığı test ediyor. Default impact: %30 loss, 60 saniye.</li><li><strong>network-failure</strong> — ağır packet loss&#39;a dayanıklılığı test ediyor. Default impact: %50 loss, 60 saniye.</li></ul><h3>8. Operasyonel Komutlar</h3><p><strong>Tüm chaos’u durdur (acil):</strong></p><pre>kubectl -n chaosplatform patch cm chaos-operator-kill-switch \<br>  -p &#39;{&quot;data&quot;:{&quot;enabled&quot;:&quot;false&quot;}}&#39;</pre><p><strong>Acil durum sonrası devam:</strong></p><pre>kubectl -n chaosplatform patch cm chaos-operator-kill-switch \<br>  -p &#39;{&quot;data&quot;:{&quot;enabled&quot;:&quot;true&quot;}}&#39;</pre><p><strong>Global schedule ayarla:</strong></p><pre>kubectl -n chaosplatform set env deployment/chaos-operator \<br>  DEFAULT_SCHEDULE=&quot;0 14 * * 1-5&quot;</pre><p><strong>Tüm schedule’ları duraklat:</strong></p><pre>kubectl -n chaosplatform set env deployment/chaos-operator \<br>  DEFAULT_SUSPEND=&quot;true&quot;</pre><p><strong>Tek experiment’ı pause et:</strong></p><pre>kubectl patch chaosexperiment &lt;name&gt; -n &lt;ns&gt; \<br>  -p &#39;{&quot;spec&quot;:{&quot;suspend&quot;:true}}&#39; --type=merge</pre><p><strong>Operatör loglarını gör:</strong></p><pre>kubectl -n chaosplatform logs deployment/chaos-operator --tail=50</pre><h3>9. QA Test Arayüzü — Chaos Engineering’i Herkese Açmak</h3><h3>Son Engel</h3><p>Operatör experiment setup’ını 33 dakikadan 1 dakikaya indirdi — ama o 1 dakika hâlâ şunları gerektiriyordu:</p><ol><li>Kubernetes cluster’a SSH veya VPN erişimi</li><li>kubectl kurulu ve configure edilmiş</li><li>YAML syntax ve CRD schema bilgisi</li><li>Status kontrol, log okuma, debug için terminal literacy</li></ol><p>SRE için sorun değil. Ama <strong>QA mühendisleri, developer’lar ve product team’ler</strong> için? Release öncesi dayanıklılık validate etmek istiyorlar ama araç setleri buna uygun değil. <strong>Sıfır kubectl, browser-based bir arayüz</strong> lazımdı — cluster içinde çalışan, doğrudan Kubernetes API ile konuşan.</p><h3>Mimari: In-Cluster Real-Time Dashboard</h3><p>QA UI, operatörle aynı chaosplatform namespace&#39;inde first-class Kubernetes workload olarak çalışıyor. Statik bir dashboard değil — <strong>ChaosExperiment custom resource&#39;ları için live, read-write control plane.</strong></p><pre>┌──────────────────────────────────────────────────────────────────────────────┐<br>│                     KUBERNETES CLUSTER                                       │<br>│                                                                              │<br>│  ┌──────────────────────────────────────────┐  ┌──────────────────────────┐  │<br>│  │   CHAOS PLATFORM CONTROLLER (Kopf)       │  │    QA UI Pod             │  │<br>│  │   ChaosExperiment CR&#39;ları reconcile eder │  │  ┌─────────┐ ┌────────┐  │  │<br>│  │   ChaosEngine oluşturur                  │◀─│  │ nginx   │ │FastAPI │  │  │<br>│  │   ChaosResult&#39;ları izler                 │  │  │ :80     │ │ :8000  │  │  │<br>│  │   CR status günceller                    │  │  │ React   │ │ K8s API│  │  │<br>│  └──────────────────────────────────────────┘  │  │ SPA     │ │ Client │  │  │<br>│              ▲         ▲                       │  └────┬────┘ └───┬────┘  │  │<br>│              │         │                       │       │          │       │  │<br>│     ChaosEngine   ChaosResult                  │       │   REST   │       │  │<br>│              │         │                       │       └────┬─────┘       │  │<br>│              │         │                       │            │             │  │<br>│  ┌───────────┴─────────┴──────┐                │            ▼             │  │<br>│  │      LitmusChaos           │                │   ServiceAccount RBAC    │  │<br>│  │      Runner Pods           │                │   (read deployments,     │  │<br>│  │      Chaos Experiments     │                │    CRUD experiments,     │  │<br>│  └────────────────────────────┘                │    read kill switch)     │  │<br>│                                                └──────────────────────────┘  │<br>│                                                                              │<br>│  ┌──────────────────────────────────────────────────────────────────────────┐│<br>│  │ Ingress: chaos-qa.preprod.internal → QA UI Service :80                  ││<br>│  └──────────────────────────────────────────────────────────────────────────┘│<br>└──────────────────────────────────────────────────────────────────────────────┘</pre><p><strong>Kritik mimari kararlar:</strong></p><ul><li><strong>In-cluster deployment</strong>: FastAPI backend load_incluster_config() kullanıyor — kubeconfig file yok, credential saklanmıyor. Kubernetes API&#39;ye pod&#39;un ServiceAccount token&#39;ı ile erişiliyor, otomatik mount ve rotate ediliyor.</li><li><strong>RBAC-scoped access</strong>: Dedicated ClusterRole UI&#39;ın tam ihtiyacını veriyor — chaosexperiments üzerinde CRUD, deployment ve namespace&#39;lerde read-only, kill switch ConfigMap&#39;inde read. Fazlası yok.</li><li><strong>İki container pod</strong>: nginx React SPA’yı port 80&#39;de serve ediyor, /api/* isteklerini port 8000&#39;deki FastAPI backend&#39;e reverse proxy yapıyor. Production&#39;da CORS sorunu yok. Tek pod, tek service, tek ingress.</li><li><strong>SQLite history</strong>: Experiment history PVC-backed SQLite database’inde persist ediliyor — pod restart’larında dayanıklı, external database dependency yok.</li></ul><h3>UI Ne Yapabiliyor? — Browser’dan Full Lifecycle</h3><p>Daha önce kubectl komutu olan her operasyon artık bir button click:</p><ul><li><strong>Allowed namespace’leri listele</strong> — kubectl get ns yerine allowed list&#39;e göre filtrelenmiş namespace dropdown.</li><li><strong>Deployment’ları listele</strong> — kubectl get deploy -n gateway yerine live replica status&#39;lu deployment dropdown.</li><li><strong>Experiment oluştur</strong> — kubectl apply -f experiment.yaml yerine &quot;tipleri seç → Run Experiment tıkla&quot;.</li><li><strong>Experiment sil</strong> — kubectl delete chaosexperiment gateway -n gateway yerine experiment card&#39;ında Delete butonu.</li><li><strong>Experiment status gör</strong> — kubectl get chaosexperiment -o yaml yerine phase badge&#39;li real-time dashboard.</li><li><strong>Schedule’ı suspend et</strong> — kubectl patch ... suspend=true yerine Suspend butonu.</li><li><strong>Acil durdur</strong> — kill-switch patch komutu yerine header’da kill switch indicator.</li><li><strong>Experiment history gör</strong> — Prometheus veya log grep yerine filtreli, CSV export’lu searchable history table.</li></ul><h3>Real-Time Kubernetes Interaction</h3><p>UI statik bir sayfa değil, demand üzerine refresh etmiyor. <strong>Cluster state’inin continuous real-time awareness’ını</strong> koruyor:</p><ol><li><strong>10 saniyelik auto-refresh</strong>: Frontend tüm aktif experiment’ları, stat’ları ve kill switch status’unu her 10 saniyede bir poll ediyor. Refresh cycle devam ederken spinning indicator görünüyor.</li><li><strong>Live countdown timer’lar</strong>: Experiment Running phase&#39;indeyken dashboard her saniye tick eden live elapsed-time counter gösteriyor — cluster&#39;da bir şeyler olduğunun anında görsel feedback&#39;i.</li><li><strong>Phase transition tracking</strong>: Operatör ChaosExperiment’ı lifecycle boyunca reconcile ederken (Pending → Running → Completed), UI her transition&#39;ı real-time color-coded phase badge&#39;leriyle yansıtıyor.</li><li><strong>Instant deployment discovery</strong>: QA engineer namespace seçtiğinde backend Kubernetes API’yi real-time sorguluyor ve deployment’ları current replica count’larıyla listeliyor. Cache değil — cluster’ın live state’i. Yeni scale edilmiş deployment anında görünüyor.</li></ol><h3>Experiment Oluşturma — Sıfır YAML, Full Güç</h3><p>QA engineer UI üzerinden experiment oluştururken şunu görüyor:</p><p><strong>Step 1 — Target Seç:</strong></p><ul><li>Filtered dropdown’dan namespace seç (sadece allowed namespace’ler görünüyor)</li><li>Live-queried listeden deployment seç (ready/total replica count görünüyor)</li><li>Sık kullanılan deployment’ları one-click erişim için pin’le</li></ul><p><strong>Step 2 — Experiment Tiplerini Seç:</strong></p><ul><li>Altı experiment type card’ı, açıklamaları ve destructive/non-destructive badge’leri</li><li>Multiple selection — operatör phased execution’ı otomatik hallediyor</li><li>Phase indicator’lar hangi experiment’ların Phase 1 vs Phase 2&#39;de çalışacağını gösteriyor</li></ul><p><strong>Step 3 — Option’ları Configure Et:</strong></p><ul><li><strong>Dry Run toggle</strong>: Tek bir ChaosEngine oluşturmadan execution planını validate et</li><li><strong>Schedule builder</strong>: Preset’li (weekdays, daily, weekly) veya custom cron input’lu görsel cron builder — human-readable preview gösteriyor (“Every weekday at 14:00 UTC”)</li><li><strong>Tag’ler</strong>: Experiment’ları kategorize et (sprint-42, team-sre, regression)</li></ul><p><strong>Step 4 — Execution Planını Review Et:</strong> Live sidebar tam olarak ne olacağını gösteriyor:</p><ul><li>Target deployment</li><li>Phase 1 experiment’ları (non-destructive)</li><li>Phase 2 experiment’ları (destructive)</li><li>Uygulanacak safety guardrail’ler</li><li>Mode badge’leri (DRY RUN, SCHEDULED, DESTRUCTIVE)</li></ul><p><strong>Step 5 — Confirm ve Run:</strong></p><ul><li>Non-destructive experiment’lar click’le anında çalışıyor</li><li>Destructive experiment’lar kırmızı uyarılı confirmation modal tetikliyor</li><li>Backend /api/experiments&#39;a POST yapıyor, o da Kubernetes API&#39;yi çağırıp ChaosExperiment CR oluşturuyor</li><li>Operatör saniyeler içinde alıp reconciliation başlatıyor</li><li>UI otomatik Dashboard’a yönlendiriyor, experiment real-time görünüyor</li></ul><h3>Confirmation Safety Net</h3><p>QA engineer dry-run mode olmadan destructive experiment tipleri (pod-failure, pod-kill) seçtiğinde, UI <strong>zorunlu confirmation modal</strong> gösteriyor:</p><pre>⚠️ Destructive Experiment<br><br>gateway/gateway üzerinde destructive chaos experiment&#39;ları<br>çalıştırmak üzeresiniz. Bu live pod&#39;ları etkileyecek.<br>┌─────────────────────────────────┐<br>│ 💥 Pod Failure                  │<br>│ ☠️ Pod Kill                     │<br>└─────────────────────────────────┘<br>[Cancel]        [Confirm &amp; Run]</pre><p>Bu bilinçli bir UX kararı — UI güvenli şeyleri kolay, tehlikeli şeyleri bilinçli yapmalı. Operatörün beş katmanlı guardrail’leriyle birlikte, istenmeyen hasar vermek aşırı zorlaşıyor.</p><h3>Dashboard — Live Cluster State</h3><p>Dashboard view tüm allowed namespace’lerdeki tüm experiment’ların real-time overview’ını sağlıyor:</p><ul><li><strong>Stats bar</strong>: Active / Passed / Failed / Scheduled / Total — Kubernetes’ten her 10 saniyede güncelleniyor</li><li><strong>Experiment card’lar</strong>: Her card experiment adı, namespace, phase badge (Running için color-coded ve animated), experiment tipleri, creation time ve schedule gösteriyor</li><li><strong>Phase filter’lar</strong>: All / Active / Completed / Scheduled view’ları arasında toggle</li><li><strong>Global search</strong>: Tüm cluster’da ad, namespace veya experiment tipine göre experiment filtrele</li><li><strong>Live countdown</strong>: Running experiment’lar pulsing animation’lı elapsed time gösteriyor</li><li><strong>Detail modal</strong>: Herhangi bir experiment card’a tıkla, operatörün CR status’una kaydettiği her phase transition dahil full status history gör</li></ul><h3>History &amp; Reporting</h3><p>UI üzerinden tetiklenen her experiment SQLite database’inde full metadata ile kaydediliyor — namespace ve deployment user selection’dan, experiment tipleri user selection’dan, phase ve result Kubernetes API’den poll ediliyor, cron schedule expression’ı, start timestamp ve duration, ve trigger source (UI-initiated experiment’lar için her zaman “qa-ui”).</p><p>Bu data şunları destekliyor:</p><ul><li><strong>14 günlük timeline chart</strong>: Günlük experiment aktivitesi, success/failure breakdown’lı bar chart</li><li><strong>Success rate widget</strong>: Overall pass rate’i namespace breakdown’lı gösteren SVG ring chart</li><li><strong>HTML report generator</strong>: Stat’lar, chart’lar ve full experiment table’lı tek tıkla indirilebilir rapor</li><li><strong>CSV export</strong>: Excel veya BI tool’larında analiz için raw data export</li></ul><h3>Topology View — Cluster-Wide Visibility</h3><p>Topology view tüm allowed namespace’leri interactive card’lar halinde grid olarak gösteriyor:</p><ul><li>Her card namespace adı, deployment count ve active/completed/failed experiment count’ları gösteriyor</li><li>Color-coded status indicator’lar: yeşil (healthy), amber pulsing animation’lı (experiment’lar çalışıyor), kırmızı (failure’lar)</li><li>Herhangi bir namespace’e tıkla, o namespace’deki tüm experiment’ları phase badge’leriyle gör</li></ul><p>Bu, leadership ve SRE manager’lara tüm organizasyondaki chaos engineering coverage’ının <strong>tek ekranlık görünümünü</strong> veriyor.</p><h3>Template’ler &amp; Quick Action’lar — Tekrarlayan İşleri Hızlandırma</h3><p>QA team’leri genelde aynı experiment’ları tekrar tekrar çalıştırıyor — UI bunu frictionless yapıyor:</p><ul><li><strong>Save as Template</strong>: Experiment configure ettikten sonra “Save Template” tıkla, full configuration’ı (namespace, deployment, tipler, schedule, tag’ler) localStorage’a kaydet</li><li><strong>Template Gallery</strong>: Kaydedilmiş template’leri browse et, rename et, sil veya trigger form’una anında yükle</li><li><strong>Quick Re-run</strong>: Son 6 experiment trigger sayfasında one-click card olarak görünüyor</li><li><strong>Pinned Deployment’lar</strong>: Sık test edilen deployment’ları session’lar arası instant access için yıldızla</li></ul><h3>Bulk Operation’lar — Enterprise Scale</h3><p>Organization-wide resilience campaign’leri için (örn. pre-release regression), Bulk Operations modal şunları sağlıyor:</p><ol><li>Birden fazla namespace’i aynı anda seç</li><li>Experiment tiplerini seç</li><li>Dry-run mode seç (bulk için önerilen)</li><li>Tek click tüm seçili namespace’lerde experiment oluşturuyor</li></ol><p>UI raporluyor: <em>“Bulk: 12 experiment oluşturuldu, 0 failed”</em> — her experiment sonra normal operatör reconciliation lifecycle’ını takip ediyor.</p><h3>Dark/Light Tema &amp; Accessibility</h3><p>UI iki tema ile geliyor, localStorage’da persist ediliyor:</p><ul><li><strong>Enterprise White</strong> (default): Temiz #F8F9FB background, #1E3A5F brand navy, kurumsal ortamlar ve projector sunumları için tasarlandı</li><li><strong>Dark Mode</strong>: #0F1117 background, #60A5FA accent blue, uzun monitoring session&#39;ları ve SRE war room&#39;ları için optimize edildi</li></ul><p>Header’daki 🌙/☀️ button veya T keyboard shortcut ile toggle et.</p><h3>Keyboard Shortcut’lar — Power User Workflow</h3><p>Keyboard-driven workflow’u tercih eden SRE engineer’lar için:</p><ul><li>1 – 5 — tab değiştir (Trigger → Dashboard → History → Templates → Topology)</li><li>/ veya Ctrl+K — search bar&#39;a focus</li><li>R — Kubernetes&#39;ten tüm data&#39;yı refresh et</li><li>N — New Experiment&#39;a git (Trigger tab)</li><li>B — Bulk Operations&#39;ı aç</li><li>T — tema toggle et</li><li>? — shortcut yardımını göster</li><li>Escape — modal&#39;ları kapat / search&#39;ü temizle</li></ul><p>Focus input field’dayken tüm shortcut’lar disabled.</p><h3>Mobile Responsive Design</h3><p>UI hareket halinde monitoring için mobile ekranlara adapte oluyor:</p><ul><li>Header navigation horizontal scroll oluyor</li><li>Stats bar 5 sütundan 2 sütuna (tablet) 1 sütuna (telefon) stack’leniyor</li><li>Experiment card’lar dikey stack’leniyor</li><li>Modal’lar full width’e uzuyor</li><li>Touch-friendly button size’ları</li></ul><h3>Deployment Model</h3><p>QA UI Kubernetes-native workload olarak deploy ediliyor:</p><pre># Tek Pod — 2 container<br>containers:<br>  - name: frontend     # nginx → React SPA :80&#39;de<br>    image: &lt;internal-registry&gt;/chaosplatform/qa-ui-frontend:latest<br>  - name: backend      # FastAPI → K8s API client :8000&#39;de<br>    image: &lt;internal-registry&gt;/chaosplatform/qa-ui-backend:latest<br>    env:<br>      - name: K8S_IN_CLUSTER<br>        value: &quot;true&quot;<br>      - name: ALLOWED_NAMESPACES<br>        value: &quot;gateway,payments,fraud,identity,lending,notifications,insurance&quot;</pre><pre># RBAC<br>ClusterRole: chaosexperiments CRUD, deployments read, configmaps read<br>ServiceAccount: chaos-qa-ui-sa (namespace: chaosplatform)</pre><pre># Storage<br>PVC: SQLite experiment history için 1Gi</pre><pre># Access<br>Ingress: chaos-qa.preprod.internal</pre><p>Tüm container image’ları internal private registry’den build ediliyor ve standart güvenlik pipeline’ından geçiyor — SAST/SCA analizi, container vulnerability scan ve image signing — deployment öncesi.</p><h3>Etki: kubectl’den Self-Service’e</h3><ul><li><strong>Chaos experiment çalıştırabilen</strong>: sadece SRE (kubectl) → herhangi bir QA engineer, developer veya manager</li><li><strong>Gereken bilgi</strong>: YAML, CRD schema, kubectl, K8s auth → browser aç, button’lara tıkla</li><li><strong>Experiment tetikleme süresi</strong>: ~1 dk (operatörle) → ~10 sn (seç, tıkla, bitti)</li><li><strong>Cluster state’i anlama süresi</strong>: kubectl get + YAML output parse → dashboard&#39;a bak</li><li><strong>Experiment history</strong>: Prometheus veya operatör loglarını grep’le → searchable table + timeline + report’lar</li><li><strong>Organization-wide coverage view</strong>: custom Grafana dashboard → built-in Topology view</li><li><strong>Release’ler için bulk test</strong>: kubectl ile script loop’ları → tek click Bulk Operations</li><li><strong>Recurring test configuration</strong>: YAML düzenle, CR’ı tekrar apply et → visual schedule builder</li></ul><p>QA UI, chaos engineering’i <strong>SRE-gated, terminal-only aktiviteden</strong> tüm engineering organizasyonuna açık <strong>self-service capability’ye</strong> dönüştürüyor.</p><h3>10. Teknoloji Stack’i</h3><ul><li><strong>Operator Runtime</strong> — Python 3.13 + Kopf 1.36, CRD reconciliation, timer handler ve leader election için.</li><li><strong>Template Engine</strong> — Jinja2 3.1, ChaosEngine YAML rendering için.</li><li><strong>Schedule Engine</strong> — croniter 6.2, cron expression parsing için.</li><li><strong>CRD</strong> — chaos.platform.io/v1alpha1 ChaosExperiment custom resource.</li><li><strong>Experiment Engine</strong> — LitmusChaos 3.9 (go-runner, chaos-runner, ChaosResult).</li><li><strong>Policy Enforcement</strong> — Kyverno, forbidden namespace ve required label için.</li><li><strong>Observability</strong> — Prometheus + Grafana, 6 metrik, 10 alert ve 2 dashboard.</li><li><strong>QA UI Frontend</strong> — React 18 + Tailwind CSS v4 (CDN), single-file SPA, build step gerektirmiyor.</li><li><strong>QA UI Backend</strong> — Python 3.13 + FastAPI 0.115, Kubernetes API client, SQLite history ve REST API.</li><li><strong>QA UI Proxy</strong> — nginx, static file serving ve backend’e reverse proxy.</li><li><strong>QA UI History</strong> — SQLite, experiment history, stat’lar ve CSV/HTML report’lar.</li><li><strong>Container Registry</strong> — internal private registry, enterprise-grade artifact storage.</li><li><strong>CI/CD</strong> — Jenkins + SAST/SCA analizi + container vulnerability scanning + image signing, build/scan/sign/deploy pipeline için.</li><li><strong>HA</strong> — 2 replica + Kopf peering, leader election ve automatic failover.</li></ul><h3>11. Önemli Çıkarımlar</h3><ol><li><strong>Değer daha az YAML yazmak değil — yedi katman operasyonel karmaşıklığı ortadan kaldırmak.</strong> Otomatikleştirdiğimiz her katman (discovery, RBAC, health check, güvenlik, scheduling, observability, lifecycle) artık unutulamaz, yanlış configure edilemez veya atlanamaz.</li><li><strong>Guardrail’ler adoption’ı mümkün kılıyor.</strong> Team’ler chaos testing’in yanlışlıkla kube-system&#39;i vuramayacağını veya tüm replica&#39;ları öldüremeyeceğini <em>bildiklerinde</em> kullanmaya başladı. Güvenlik güveni mümkün kıldı.</li><li><strong>Global default + local override doğru abstraction.</strong> Operatör seviyesinde tek bir cron expression her servise recurring test veriyor. İsteyen team kendi ihtiyacına göre override edebilir. Sıfır koordinasyon gerekiyor.</li><li><strong>İlk testin fail edecek — ve amaç da bu.</strong> İlk pod-failure testimiz pod’ların %100&#39;ünü öldürdü ve servisin sıfır graceful degradation’ı olduğunu kanıtladı. Tek başına bu bulgu tüm projeyi haklı çıkardı.</li><li><strong>Platform, uzman olmayanlar kullanana kadar tamamlanmış sayılmaz.</strong> Operatör SRE engineer’lar için karmaşıklık problemini çözdü. QA UI herkes için erişilebilirlik problemini çözdü. Bir QA engineer tek satır YAML yazmadan veya kubectl’e dokunmadan browser’dan chaos experiment tetikleyebildiğinde, izleyebildiğinde ve raporlayabildiğinde — chaos engineering SRE disiplini olmaktan çıkıp organizasyonel capability’ye dönüşüyor.</li></ol><p>Mert Polat, Intertech (DenizBank / Emirates NBD Group) bünyesinde Expert SRE ve LitmusChaos Türkiye Topluluk Lideri olarak görev yapmaktadır. Kurum içinde chaos engineering girişimini başlatmış; sistem mimarisini tasarlayan Architect SRE Buğra Çakmak ile yakın iş birliği içinde çalışmış ve bu sürecin hayata geçirilmesini destekleyen yöneticileri Salih Eligüzel’in liderliğinde bu inisiyatifi ileri taşımıştır.</p><p>Birlikte, servislerin hatalara karşı dayanıklılığını kanıtlayan production-grade bir chaos engineering platformu geliştirmişlerdir — dayanıklılık testlerini otomatikleştiren Kubernetes operatörlerinden, chaos engineering’i organizasyon genelinde herkes için erişilebilir hale getiren tarayıcı tabanlı arayüzlere kadar uzanan bir yapı inşa edilmiştir.</p><p>Intertech, <a href="http://litmuschaos.io">litmuschaos.io</a> üzerinde resmi bir LitmusChaos kullanıcısı (adopter) olarak listelenmektedir.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2804f704144a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/intertechit/productionda-chaos-engineering-platformu-manuel-i%CC%87%C5%9Flerden-oto-dayan%C4%B1kl%C4%B1l%C4%B1k-testine-2804f704144a">Production’da Chaos Engineering Platformu: Manuel İşlerden Oto. Dayanıklılık Testine</a> was originally published in <a href="https://medium.com/intertechit">Intertech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[RediSearch ile Real-Time Search Mimarisi ve .NET Entegrasyonu]]></title>
            <link>https://medium.com/intertechit/redisearch-ile-real-time-search-mimarisi-ve-net-entegrasyonu-d0d70be6526e?source=rss----d21876bad59---4</link>
            <guid isPermaLink="false">https://medium.com/p/d0d70be6526e</guid>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[redisearch]]></category>
            <category><![CDATA[elasticsearch]]></category>
            <category><![CDATA[autocomplete]]></category>
            <category><![CDATA[redis]]></category>
            <dc:creator><![CDATA[Cihat Solak]]></dc:creator>
            <pubDate>Fri, 09 Jan 2026 12:21:27 GMT</pubDate>
            <atom:updated>2026-01-09T12:21:23.001Z</atom:updated>
            <content:encoded><![CDATA[<h3>RediSearch ile Real-Time Search Mimarisi ve .NET Entegrasyonu</h3><h4>Real-Time Search Architecture with RediSearch and .NET Integration</h4><p>Modern yazılım mimarilerinde performans, kullanıcı deneyimini doğrudan etkiler. Hepimiz o milisaniyeler içinde tepki veren autocomplete kutularına alıştık; açıkçası kullanıcıların beklemeye pek tahammülü yok. RDBMS tarafında veri bütünlüğü (integrity) konusunda içimiz rahat olsa da, iş metin tabanlı aramalara geldiğinde, özellikle o meşhur LIKE %...% sorgularının yarattığı <strong>performans maliyeti</strong> can sıkıcı olabiliyor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*q38N6zJiNl64OdR79na0YQ.jpeg" /><figcaption>Redis Stack, Redis’i yalnızca bir key-value store olmaktan çıkarıp arama, JSON, zaman serileri ve grafik gibi gelişmiş veri yapılarını tek bir paket altında sunan entegre bir platformdur.</figcaption></figure><p>Bu darboğazı aşmak için yıllardır başvurulan ilk çözüm genelde Elasticsearch oldu. Ancak in-memory teknolojilerin olgunlaşmasıyla birlikte RediSearch, özellikle real-time senaryolarda masadaki dengeyi değiştirecek güçlü bir oyuncu haline geldi.</p><h4>RediSearch Nedir?</h4><p>RediSearch, özünde Redis’in o bildiğimiz yüksek performanslı yapısının üzerine C ile yazılmış bir modül olarak geliyor. Redis denince aklımıza ilk gelen standart Key-Value eşleşmesinin sınırlarını aşıp, veriyi <strong>Ters Dizin (Inverted Index)</strong> yapısıyla tutmamıza olanak sağlıyor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/588/1*dT1haOpHJrgZh7STyj4hnw.jpeg" /><figcaption><strong>Ters Dizin (Inverted Index)</strong>, kelimeleri anahtar olarak tutup bu kelimelerin geçtiği dokümanlara işaret eden ve hızlı aramayı mümkün kılan bir veri yapısıdır.</figcaption></figure><p><strong>Peki kaputun altında ne dönüyor?</strong> Normalde Redis’te veriye ulaşmak için elinizde mutlaka bir key olması gerekir. RediSearch ise oyunun kurallarını değiştirip verinin içeriğini indeksliyor. Örneğin bir ürün açıklamasını alıyor, parçalıyor (<strong>tokenization</strong>), kelime köklerine iniyor (<strong>stemming</strong>) ve <strong>hangi kelimenin nerede geçtiğini tamamen RAM üzerinde haritalıyor. </strong>Tüm operasyon bellekte döndüğü için de milyonlarca kayıt arasında arama yapmak milisaniye değil, mikrosaniye mertebesinde gerçekleşebiliyor.</p><p><strong>Temel Yetenekleri:</strong></p><ul><li><strong>Full-Text Search:</strong> Eş anlamlılar, stop-words, çok dilli kök bulma.</li><li><strong>Numeric &amp; Geo Filtering:</strong> Konum tabanlı veya fiyat aralığına göre ultra hızlı filtrelemeler.</li><li><strong>Aggregation:</strong> Group by, sort, apply fonksiyonları (SQL benzeri).</li><li><strong>Auto-Complete:</strong> Fuzzy (bulanık) arama desteği ile hatalı yazımları tolere eden tamamlama önerileri.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*yPblvMZAFH4DRO8a1UWGKw.png" /><figcaption>RediSearch, Redis veritabanını zengin sorgulama yetenekleri, ikincil indeksleme ve karmaşık tam metin arama (full-text search) özellikleriyle donatan, bellek içi hızında çalışan güçlü bir arama motoru modülüdür.</figcaption></figure><p><strong>Stop-words,</strong> arama sonuçlarını anlamlı şekilde etkilemeyen ve performans için göz ardı edilen sık kullanılan kelimelerdir.</p><p>Türkçe: <em>ve, ile, için, da, de, bu, şu</em></p><p>İngilizce: <em>the, is, at, of, and</em></p><p><strong>Fuzzy search</strong>, yazım hatalarına rağmen benzer kelimeleri eşleştirerek arama deneyimini kesintisiz hâle getirir. Kelimeler arasındaki <strong>edit distance (Levenshtein mesafesi)</strong> gibi ölçütler kullanılarak benzerlik hesaplanır. Genellikle harf hatalarını, eksik karakterleri, küçük yazım farklarını tolere eder.</p><p>Kullanıcı: redi</p><p>Sistem: redis</p><h4>Elasticsearch vs RediSearch</h4><p>Projelerin tasarım aşamasında en sık karşılaştığımız yol ayrımlarından biri: <em>“Hangi teknolojiyi seçmeliyiz?”</em> Sektördeki birçok e-ticaret devinin Elasticsearch kullanıyor olması tesadüf değil; orada yılların getirdiği bir ekosistem ve güven var. Ancak yazılım dünyasında <strong>“Silver Bullet”</strong> (her sorunu çözen tek araç) diye bir şey yok; ihtiyaçlara göre doğru teraziyi kurmak, yani <strong>Trade-off</strong> (ödünleşim) analizi yapmak zorundayız.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*xw1K5FEOQkJKaEeX6iUm-g.png" /><figcaption>Elasticsearch; Apache Lucene altyapısı üzerine inşa edilmiş, dağıtık (distributed) mimaride çalışan, verileri JSON formatında saklayan ve RESTful API üzerinden yönetilen, yüksek ölçeklenebilirliğe sahip açık kaynaklı bir <strong>arama ve analiz motorudur.</strong></figcaption></figure><p><strong>[Silver Bullet]:</strong> Yazılım dünyasında <strong>her problemi tek başına ve kusursuzca çözdüğü varsayılan araç veya teknoloji</strong> anlamında kullanılan bir ifadedir.</p><p><strong>[Trade-off]:</strong> Bir kazanım elde ederken <strong>başka bir avantajdan bilinçli olarak vazgeçme</strong> durumudur.</p><pre>ÖZELLİK           ELASTICSEARCH (ES)                     REDISEARCH<br>------------------------------------------------------------------------------------------<br>Temel Teknoloji   Apache Lucene (Java)                   Redis Module (C)<br>------------------------------------------------------------------------------------------<br>Veri Saklama      Disk Ağırlıklı (RAM önbellek)          Bellek (RAM) Ağırlıklı<br>------------------------------------------------------------------------------------------<br>Performans        Hızlı (Milisaniyeler)                  Ultra Hızlı (ES&#39;den %50&#39;e varan hızlı)<br>------------------------------------------------------------------------------------------<br>Maliyet           Disk ucuzdur, ekonomiktir              RAM pahalıdır, maliyet artar<br>------------------------------------------------------------------------------------------<br>Sorgu Dili        Çok zengin JSON tabanlı DSL            Basit, SQL benzeri sözdizimi<br>------------------------------------------------------------------------------------------<br>Karmaşıklık       Yüksek (JVM, Sharding vb.)             Düşük (Redis yönetimi ile aynı)</pre><h4>Neden Hâlâ Elasticsearch?</h4><p>RediSearch hızlı olsa da, aşağıdaki durumlarda Elasticsearch (veya OpenSearch) mimari açıdan daha doğru tercihtir:</p><ol><li><strong>Maliyet ve Veri Boyutu:</strong> 50 Milyon ürünlük bir kataloğu ve yıllara yayılan logları RAM’de (RediSearch) tutmak, bulut maliyetlerini (AWS/Azure) çok ciddi artırır. ElasticSearch bu veriyi ucuz disklerde tutar.</li><li><strong>Derin Analitik ve Raporlama:</strong> “Son 6 ayda X kategorisine bakan ama Y ürününü almayan kullanıcıların yaş dağılımı” gibi karmaşık iş zekası sorgularında ElasticSearch çok daha yeteneklidir.</li><li><strong>Ekosistem (ELK Stack):</strong> ElasticSearch sadece arama motoru değil, Kibana ile entegre devasa bir log yönetim platformudur.</li></ol><h4>Ne Zaman RediSearch?</h4><ul><li><strong>Instant Search (Anlık Arama):</strong> Kullanıcı harf bastığı anda tepki vermesi gereken Autocomplete modülleri.</li><li><strong>Önbellek Katmanı:</strong> Ana veri tabanının önünde duran, “Hot Data” (çok sık erişilen) arama motoru olarak.</li><li><strong>Ephemeral Data:</strong> Oturum bazlı veya geçici arama verileri.</li></ul><blockquote>Eğer sisteminizde halihazırda Redis kullanıyorsanız (Cache, Session vb. yönetimi için) ve sadece basit bir <strong>“Autocomplete”</strong> veya <strong>“Ürün Arama”</strong> özelliğine ihtiyacınız varsa; gidip sıfırdan bir Elasticsearch cluster’ı kurmak, yönetmek ve bakımını yapmak <strong>Overengineering</strong> (Aşırı Mühendislik) olabilir. Mevcut Redis’inizi RediSearch modülüyle güçlendirip, ekstra operasyonel maliyet yaratmadan bu işi çözmek çoğu zaman en akılcı yol olabilir.</blockquote><h4>Docker ile RediSearch</h4><p>RediSearch’ü kullanmak için standart <strong>Redis imajı yeterli değildir</strong>. İçinde modüllerin yüklü olduğu redis-stack-server imajını kullanmalıyız.</p><p><a href="https://hub.docker.com/r/redis/redis-stack-server">redis/redis-stack-server - Docker Image</a></p><p>Aşağıdaki docker-compose.yml dosyası, hem arama motorunu hem de verileri görselleştirebileceğiniz <strong>RedisInsight</strong> arayüzünü ayağa kaldırır.</p><pre>version: &#39;3.8&#39;<br>services:<br>  redis-stack:<br>    image: redis/redis-stack:latest<br>    container_name: redis-search-engine<br>    ports:<br>      - &quot;6379:6379&quot;  # Uygulama bağlantı portu<br>      - &quot;8001:8001&quot;  # RedisInsight UI (Görselleştirme)<br>    environment:<br>      - REDIS_ARGS=&quot;--requirepass 123456&quot; # Prod için şifre<br>    volumes:<br>      - ./redis-data:/data<br>    deploy:<br>      resources:<br>        limits:<br>          memory: 2G # Bellek yönetimi kritiktir</pre><p>Çalıştırmak için:</p><pre>docker-compose up -d</pre><p>Tarayıcınızdan http://localhost:8001 adresine giderek veri tabanınızı izleyebilir veya Redis Insight uygulamasını kurabilirsiniz.</p><h4>Redis OM</h4><p>Geçmişte RediSearch ile çalışırken FT.SEARCH index &quot;@name:...&quot; gibi string komutlar (magic strings) kullanılırdı. Bu yöntem hataya açıktır ve bakımı zordur.</p><p>Modern .NET mimarisinde, <strong>Redis OM .NET</strong> kütüphanesini kullanarak Entity Framework benzeri, tip güvenli (type-safe) ve LINQ destekli bir yapı kuracağız.</p><p>Gerekli paketi yükleyin:</p><pre>dotnet add package Redis.OM</pre><p><a href="https://www.nuget.org/packages/Redis.OM/">Redis.OM 1.1.0</a></p><p>Veri tabanı tablosu tanımlar gibi, Redis içinde saklayacağımız nesneyi ve indeksleme stratejisini Attribute&#39;lar ile belirtebilirsiniz.</p><pre>/// &lt;summary&gt;<br>/// RedisSearch üzerinde Türkçe içerik için optimize edilmiş ürün dokümanını temsil eder.<br>/// Türkçe kök bulma, stop-word filtreleme ve performanslı indeksleme ayarlarını içerir.<br>/// &lt;/summary&gt;<br>[Document(<br>    /// &lt;summary&gt;<br>    /// Verilerin Redis tarafında Hash yapısı ile saklanacağını belirtir.<br>    /// Hash, RedisSearch için en performanslı depolama tipidir.<br>    /// &lt;/summary&gt;<br>    StorageType = StorageType.Hash,<br><br>    /// &lt;summary&gt;<br>    /// Redis key’leri için kullanılacak prefix bilgisini tanımlar.<br>    /// Index tarama alanını daraltarak performansı artırır.<br>    /// &lt;/summary&gt;<br>    Prefixes = new[] { &quot;Product&quot; },<br><br>    /// &lt;summary&gt;<br>    /// RedisSearch index adını belirtir.<br>    /// Varsayılan adlandırma yerine okunabilir ve yönetilebilir bir isim sağlar.<br>    /// &lt;/summary&gt;<br>    IndexName = &quot;search:idx:products:tr&quot;,<br><br>    /// &lt;summary&gt;<br>    /// Full-Text arama sırasında kullanılacak dili belirtir.<br>    /// Türkçe kök bulma ve metin analizi davranışlarını aktif eder.<br>    /// &lt;/summary&gt;<br>    Language = &quot;turkish&quot;,<br><br>    /// &lt;summary&gt;<br>    /// Indexleme sırasında göz ardı edilecek Türkçe stop-word listesini tanımlar.<br>    /// Anlamsız kelimeleri eleyerek arama kalitesini ve performansı artırır.<br>    /// &lt;/summary&gt;<br>    Stopwords = new[]<br>    {<br>        &quot;ve&quot;, &quot;ile&quot;, &quot;için&quot;, &quot;bu&quot;, &quot;şu&quot;, &quot;bir&quot;,<br>        &quot;da&quot;, &quot;de&quot;, &quot;mi&quot;, &quot;mı&quot;, &quot;mu&quot;, &quot;mü&quot;<br>    }<br>)]<br>public class Product<br>{<br>    /// &lt;summary&gt;<br>    /// Redis üzerinde dokümanın benzersiz kimliğini temsil eder.<br>    /// Varsayılan olarak ULID tabanlı otomatik ID üretimi kullanılır.<br>    /// &lt;/summary&gt;<br>    [RedisIdField]<br>    public string Id { get; set; }<br><br>    /// &lt;summary&gt;<br>    /// Ürün adını temsil eder.<br>    /// Full-Text arama, sıralama ve metin analizi için indekslenir.<br>    /// &lt;/summary&gt;<br>    [Searchable(Sortable = true)] //Alanı full-text arama için indeksler ve sonuçların bu alan üzerinden sıralanmasını sağlar.<br>    public string Name { get; set; }<br><br>    /// &lt;summary&gt;<br>    /// Ürün açıklamasını temsil eder.<br>    /// Full-Text arama için metin analizi uygulanır.<br>    /// &lt;/summary&gt;<br>    [Searchable] //Alanı full-text arama için indeksler, metin analizi yapar ancak sıralamaya izin vermez.<br>    public string Description { get; set; }<br><br>    /// &lt;summary&gt;<br>    /// Ürünün ait olduğu kategori bilgisini temsil eder.<br>    /// Exact match ve filtreleme senaryoları için indekslenir.<br>    /// &lt;/summary&gt;<br>    [Indexed]<br>    public string Category { get; set; }<br><br>    /// &lt;summary&gt;<br>    /// Ürünün satış fiyatını temsil eder.<br>    /// Sayısal filtreleme ve sıralama işlemleri için indekslenir.<br>    /// &lt;/summary&gt;<br>    [Indexed(Sortable = true)] //Full-text arama yapmadan filtreleme ve aralık sorgularını hızlı çalıştırmak ve sonuçları bu alana göre sıralamak için kullanılır.<br>    public double Price { get; set; }<br>}<br>}</pre><p><a href="https://redis.io/docs/latest/integrate/redisom-for-net/">RedisOM for .NET</a></p><p>Aşağıdaki servis, indeks oluşturmayı (migration), veri eklemeyi ve tip güvenli aramayı yönetir. Ayrıca “Autocomplete” için hibrit bir yaklaşım içerir.</p><pre>public sealed class ProductSearchService(<br>    IAutocompleteService autocompleteService,<br>    IRedisConnection redisConnection,<br>    IRedisCollection&lt;Product&gt; productRedisCollection) : IProductSearchService<br>{<br>    /// &lt;inheritdoc /&gt;<br>    public async Task InitializeIndexAsync()<br>    {<br>        // Index zaten varsa tekrar oluşturmaya çalışması Redis OM tarafından yönetilir<br>        await redisConnection.CreateIndexAsync(typeof(Product));<br>    }<br><br>    /// &lt;inheritdoc /&gt;<br>    public async Task IndexRangeAsync(IEnumerable&lt;Product&gt; products)<br>    {<br>        if (!products.Any()) return;<br><br>        // 1. Redis OM Collection&#39;a TOPLU Ekleme (Bulk Insert)<br>        await productRedisCollection.InsertAsync(products);<br><br>        // 2. Autocomplete İndeksine Ekleme (Paralel)<br>        // Autocomplete servisi tekil çalıştığı için bunları paralel task olarak ateşliyoruz.<br>        var autocompleteTasks = products<br>            .Select(autocompleteService.IndexAsync);<br><br>        await Task.WhenAll(autocompleteTasks);<br>    }<br>}</pre><pre>public sealed class AutocompleteService(<br>    IRedisConnection connection, <br>    IConnectionMultiplexer connectionMultiplexer) : IAutocompleteService<br>{<br>    private const string AutocompleteDictionaryKey = &quot;autocomplete:products:dict:tr&quot;;<br><br>    public async Task IndexAsync(Product product)<br>    {<br>        string payload = JsonSerializer.Serialize(product);<br><br>        // 1. StackExchange.Redis&#39;in &quot;IBatch&quot; özelliğini kullanıyoruz.<br>        // Bu, komutları bellekte biriktirir, ağa göndermez.<br>        var batch = connectionMultiplexer.GetDatabase().CreateBatch();<br><br>        // Geri dönüş değerlerini beklemek için task listesi<br>        List&lt;Task&gt; tasks = [];<br><br>        foreach (var (term, score) in product.Name.ToAutocompleteTerms())<br>        {<br>            // Batch üzerine ekliyoruz (Henüz Redis&#39;e gitmedi)<br>            // FireAndForget: Cevabı bekleme, sadece gönder (Hız için kritik)<br>            Task task = batch.ExecuteAsync(<br>                &quot;FT.SUGADD&quot;,<br>                AutocompleteDictionaryKey,<br>                term,<br>                score,<br>                &quot;PAYLOAD&quot;,<br>                payload<br>            );<br><br>            tasks.Add(task);<br>        }<br><br>        // 2. Tüm komutları TEK BİR ağ paketinde sunucuya fırlat<br>        batch.Execute();<br><br>        // 3. İşlemlerin tamamlanmasını bekle<br>        await Task.WhenAll(tasks);<br>    }<br><br>    public async Task&lt;List&lt;Product&gt;&gt; SuggestAsync(string prefix)<br>    {<br>        List&lt;object&gt; args = [AutocompleteDictionaryKey, prefix];<br><br>        if (prefix.Length &gt;= 3) // Performans: Çok kısa sorgularda (1-2 harf) maliyeti düşürmek için Fuzzy modu kapatılabilir.<br>        {<br>            args.Add(&quot;FUZZY&quot;);<br>        }<br><br>        args.Add(&quot;WITHPAYLOADS&quot;);<br>        args.Add(&quot;MAX&quot;);<br>        args.Add(&quot;5&quot;);<br><br>        RedisReply[] products = await connection.ExecuteAsync(&quot;FT.SUGGET&quot;, [.. args]);<br><br>        if (products == null || products.Length == 0) return [];<br><br>        return [..products<br>            .Where((_, index) =&gt; index % 2 == 1) // Sadece payload (tekil indeksler)<br>            .Select(product =&gt; JsonSerializer.Deserialize&lt;Product&gt;(product.ToString()))<br>            .DistinctBy(p =&gt; p.Id) // Tekilleştirme<br>            .Take(5)];<br>    }<br>}</pre><p><strong>💡 Performans İpucu: Fuzzy Kullanımında Eşik Değeri</strong> FT.SUGGET komutunda FUZZY parametresi, Levenshtein mesafesi hesaplaması nedeniyle ek işlemci maliyeti (CPU overhead) yaratır. Özellikle 1 veya 2 karakterlik çok kısa prefix aramalarında, potansiyel eşleşme havuzu çok geniş olacağından bu maliyet katlanarak artar ve gecikmelere (latency) yol açabilir.</p><p><strong>Öneri:</strong> FUZZY özelliğini koşullu hale getirin. Prefix uzunluğu <strong>3 karakterin altındaysa</strong> standart arama yapın; sadece 3 ve üzeri karakterlerde bulanık aramayı devreye alın. Bu yaklaşım, kaynak kullanımı ile kullanıcı deneyimi arasındaki en optimum dengeyi sağlar.</p><h4>Kullanım Senaryosu</h4><pre>var builder = WebApplication.CreateBuilder(args);<br><br>builder.Services.AddRedisInfrastructure(builder.Configuration);<br><br>var app = builder.Build();<br><br>/// &lt;summary&gt;<br>/// RedisSearch index’lerini oluşturur (startup veya manuel tetikleme).<br>/// &lt;/summary&gt;<br>app.MapPost(&quot;/search/init&quot;, async (IProductSearchService service) =&gt;<br>{<br>    await service.InitializeIndexAsync();<br>    return Results.Ok(&quot;Index oluşturuldu.&quot;);<br>});<br><br>/// &lt;summary&gt;<br>/// Tip güvenli RedisSearch sorgusu.<br>/// &lt;/summary&gt;<br>app.MapGet(&quot;/products/autocomplete&quot;, async (<br>    string prefix,<br>    IAutocompleteService service) =&gt;<br>{<br>    var result = await service.SuggestAsync(prefix);<br>    return Results.Ok(result);<br>});<br><br>app.Run();</pre><h4><strong>Sonuç: Dengeli Bir Mimari</strong></h4><p>RediSearch, hem kurulum basitliği hem de in-memory çalışmanın getirdiği o agresif hızıyla modern stack’lerde kendine sağlam bir yer edindi. Özellikle Redis OM gibi kütüphanelerle .NET tarafındaki geliştirici deneyimi de gayet tatmin edici.</p><p>Burada benim şahsi favorim ve önerim <strong>Hibrit Mimari</strong> yaklaşımı:</p><ul><li>Arka plandaki log analizleri, devasa veri ambarları veya karmaşık raporlamalar için <strong>Elasticsearch</strong> gücünü koruyor, orada macera aramaya gerek yok.</li><li>Ama iş, kullanıcının birebir etkileşime girdiği “Arama Kutusu” veya anlık filtrelemelere gelince <strong>RediSearch </strong>kullanımı değerlendirilmelidir.</li></ul><p>Bu kurgu, hem altyapı maliyetlerini optimize etmemizi sağlıyor hem de kullanıcıya o beklediği ışık hızında deneyimi sunuyor.</p><p><a href="https://github.com/cihatsolak/net10-redisearch-dotnet-integration">GitHub - cihatsolak/net10-redisearch-dotnet-integration: A .NET 10-based integration project demonstrating how to use RediSearch with Redis in modern .NET applications. It focuses on indexing, querying, and full-text search capabilities, providing practical examples and a clean setup for learning and experimentation.</a></p><p>Otomatik tamamlama, kullanıcı deneyiminin sadece ilk adımıydı. RediSearch ile milyonlarca döküman içinde milisaniyeler süren aramalar yapmak, coğrafi (geo-spatial) filtrelemeler uygulamak ve veriden anlamlı raporlar çıkarmak mümkün.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*qQnGmAk_qgrNWwMwQcb7Jg.gif" /></figure><p>Bir sonraki yazımda, RediSearch’ün komut setini (FT.CREATE, FT.SEARCH, FT.EXPLAIN) masaya yatıracak ve gerçek bir arama motorunun mimarisini kurgulayacağız.</p><p>Görüşmek üzere.</p><ul><li><a href="https://redis.io/docs/latest/develop/ai/search-and-query/">Redis Query Engine</a></li><li><a href="https://github.com/redis/redis-om-dotnet">GitHub - redis/redis-om-dotnet: Object mapping, and more, for Redis and .NET</a></li><li><a href="https://hub.docker.com/r/redis/redis-stack">redis/redis-stack - Docker Image</a></li><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Elastic fundamentals | Elastic Docs</a></li><li><a href="https://en.wikipedia.org/wiki/Inverted_index">Inverted index - Wikipedia</a></li><li><a href="https://university.redis.io/academy">Redis University</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d0d70be6526e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/intertechit/redisearch-ile-real-time-search-mimarisi-ve-net-entegrasyonu-d0d70be6526e">RediSearch ile Real-Time Search Mimarisi ve .NET Entegrasyonu</a> was originally published in <a href="https://medium.com/intertechit">Intertech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Scalar ile .NET API Dokümantasyonunda Yeni Dönem]]></title>
            <link>https://medium.com/intertechit/scalar-ile-net-api-dok%C3%BCmantasyonunda-yeni-d%C3%B6nem-d18875640af5?source=rss----d21876bad59---4</link>
            <guid isPermaLink="false">https://medium.com/p/d18875640af5</guid>
            <category><![CDATA[api-documentation]]></category>
            <category><![CDATA[rest-api]]></category>
            <category><![CDATA[open-api]]></category>
            <category><![CDATA[scaler-doc]]></category>
            <category><![CDATA[dotnet-core]]></category>
            <dc:creator><![CDATA[Cihat Solak]]></dc:creator>
            <pubDate>Fri, 20 Jun 2025 07:34:42 GMT</pubDate>
            <atom:updated>2025-06-20T07:34:42.838Z</atom:updated>
            <content:encoded><![CDATA[<h3>Scalar ile .NET API Dokümantasyonunda Yeni Dönem</h3><h4>New Era in .NET API Documentation with Scalar</h4><p>Modern .NET ekosisteminde API dokümantasyonu, yazılım geliştirme sürecinin vazgeçilmez bir parçası haline geldi. OpenAPI standartları sayesinde API’ler daha anlaşılır oluyor; bu da ekip içi iletişimi güçlendiriyor, test otomasyonunu kolaylaştırıyor ve istemci kütüphanelerinin otomatik olarak üretilmesini sağlıyor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JOYNBtOMw8sBOrGWDOsi-g.png" /><figcaption>The modern open-source developer experience platform for your APIs.</figcaption></figure><h4>OpenAPI Nedir ve Neden Önemlidir?</h4><p><a href="https://www.openapis.org/">OpenAPI</a>, API’lerin yapılandırılmış ve standart bir biçimde tanımlanmasını sağlayan bir spesifikasyondur. JSON veya YAML formatında yazılan bu doküman; endpoint’leri, istek ve yanıt modellerini, yetkilendirme yöntemlerini ve hata kodlarını tanımlar. Böylece:</p><blockquote>1️ API geliştiriciler ve kullanıcılar ortak bir anlaşmaya sahip olur.</blockquote><blockquote>2️ Kod üretme, test ve dokümantasyon otomasyonu kolaylaşır.</blockquote><blockquote>3️ Araçlar tarafından interaktif dokümanlar üretilebilir.</blockquote><p>Özetle <a href="https://www.openapis.org/"><strong>OpenAPI</strong></a>, API yaşam döngüsünü hızlandıran ve standartlaştıran evrensel bir dildir.</p><h4>Scalar Nedir?</h4><p>Scalar, OpenAPI dokümanlarını modern, hızlı ve kullanıcı dostu bir arayüzle sunmak için geliştirilmiş açık kaynaklı bir araçtır. Swagger UI’a göre daha <strong>hafif</strong>, daha <strong>şık </strong>ve <strong>mobil uyumlu</strong> olmasıyla dikkat çeker.</p><p>Scalar, .NET API dokümantasyonu için hızlı yükleme süresiyle dikkat çeker; özellikle büyük projelerde minimal kaynak kullanımı sayesinde önemli bir performans avantajı sağlar. Duyarlı tasarımı sayesinde her cihazda sorunsuz görüntülenebilir, bu da geliştiricilerin mobil ortamlarda bile dokümantasyona kolayca erişmesini mümkün kılar. Entegre “Try-it-now” özelliği ile geliştiriciler, belgeler üzerinden doğrudan API çağrıları yaparak test süreçlerini hızlı ve interaktif bir şekilde gerçekleştirebilir. Ayrıca tema ve arayüz ayarlarının kolayca özelleştirilebilmesi sayesinde, Scalar farklı kurumsal kimliklere rahatlıkla uyum sağlayabilir.</p><h4>Scalar’ı ASP.NET Core Projesinde Kullanmak</h4><p>Scalar’ı kullanmaya başlamak için projenize Microsoft.AspNetCore.OpenApiveScalar.AspNetCore<br>NuGet paketlerini ekleyin. Ardından Program.cs dosyanızda OpenAPI ve Scalar ayarlarını yapın.</p><pre>var builder = WebApplication.CreateBuilder(args);<br><br>builder.Services.AddOpenApi();<br><br>var app = builder.Build();<br><br>app.MapOpenApi();<br>app.MapScalarApiReference();</pre><p>Bu basit kurulumla /scalar endpoint’i üzerinden şık bir dokümantasyona sahip olursunuz.</p><ul><li><a href="https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi">Microsoft.AspNetCore.OpenApi 9.0.6</a></li><li><a href="https://www.nuget.org/packages/Scalar.AspNetCore/">Scalar.AspNetCore 2.4.13</a></li></ul><h4>Güvenlik ve Yetkilendirme</h4><p>Bearer token (JWT) gibi yaygın güvenlik şemalarını Scalar dokümantasyonuna entegre etmek kolaydır. Konfigürasyonlarınızı aşağıdaki gibi yapabilirsiniz:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vbOnKE9Qyb7fDKqfblAzuA.png" /></figure><pre>builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)<br>    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme,<br>    options =&gt;<br>    {<br>        options.TokenValidationParameters = new TokenValidationParameters<br>        {<br>        };<br>    });<br><br><br>builder.Services.AddOpenApi(&quot;v1&quot;, options =&gt;<br>{<br>    options.AddDocumentTransformer&lt;BearerSecuritySchemeTransformer&gt;(); //JWT<br>});</pre><pre>public sealed class BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider)<br>: IOpenApiDocumentTransformer<br>{<br>    public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)<br>    {<br>        var authenticationSchemes = await authenticationSchemeProvider.GetAllSchemesAsync();<br>        if (!authenticationSchemes.Any(scheme =&gt; scheme.Name == JwtBearerDefaults.AuthenticationScheme))<br>            return;<br><br>        AddBearerSecurityScheme(document);<br>        ApplySecurityRequirements(document);<br>    }<br><br>    private static void AddBearerSecurityScheme(OpenApiDocument document)<br>    {<br>        document.Components ??= new OpenApiComponents();<br>        document.Components.SecuritySchemes ??= new Dictionary&lt;string, OpenApiSecurityScheme&gt;();<br><br>        document.Components.SecuritySchemes[JwtBearerDefaults.AuthenticationScheme] = new OpenApiSecurityScheme<br>        {<br>            Type = SecuritySchemeType.Http,<br>            Scheme = &quot;bearer&quot;,<br>            In = ParameterLocation.Header,<br>            BearerFormat = &quot;JWT&quot;,<br>            Reference = new OpenApiReference<br>            {<br>                Id = JwtBearerDefaults.AuthenticationScheme,<br>                Type = ReferenceType.SecurityScheme<br>            }<br>        };<br>    }<br><br>    private static void ApplySecurityRequirements(OpenApiDocument document)<br>    {<br>        foreach (var operation in document.Paths.Values.SelectMany(path =&gt; path.Operations.Values))<br>        {<br>            operation.Security ??= [];<br>            operation.Security.Add(new OpenApiSecurityRequirement<br>            {<br>                [new OpenApiSecurityScheme<br>                {<br>                    Reference = new OpenApiReference<br>                    {<br>                        Id = JwtBearerDefaults.AuthenticationScheme,<br>                        Type = ReferenceType.SecurityScheme<br>                    }<br>                }] = Array.Empty&lt;string&gt;()<br>            });<br>        }<br>    }<br>}</pre><p>Scalar aynı zamanda farklı güvenlik şemaları için kolayca genişletilebilir. Örneğin <strong>API key</strong>,<strong> </strong><a href="https://auth0.com/intro-to-iam/what-is-oauth-2"><strong>OAuth2</strong></a> gibi protokolleri destekler. Böylece dokümantasyon hem kapsamlı hem güvenli olur.</p><h4>Versiyonlama Desteği</h4><p>Kurumsal projelerde API versiyonlaması kaçınılmazdır. <strong>Scalar, farklı OpenAPI dokümanlarını versiyonlara göre ayırmanı ve aynı kullanıcı arayüzü altında birden fazla API versiyonunu sunmanı destekler.</strong> Bu özellik sayesinde, hem geçmiş versiyonları koruyabilir hem de yeni versiyonları aşamalı olarak yayınlayabilirsin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Tnp5xmOyHTbyXn6IiS6yzg.png" /></figure><p>Program.cs içinde versiyonlara göre Scalar yapılandırması:</p><pre>// Using AddDocument with different route patterns<br>app.MapScalarApiReference(options =&gt;<br>{<br>    options<br>        .AddDocument(&quot;v1&quot;, &quot;Production API&quot;, &quot;api/{documentName}/spec.json&quot;)<br>        .AddDocument(&quot;v2-beta&quot;, &quot;Beta API&quot;, &quot;beta/openapi.json&quot;);<br>});<br><br>// Using AddDocuments with string array (uses default route pattern)<br>string[] versions = [&quot;v1&quot;, &quot;v2&quot;];<br>app.MapScalarApiReference(options =&gt; options.AddDocuments(versions));<br><br>// Using AddDocuments with ScalarDocument objects<br>var documents = new[]<br>{<br>    new ScalarDocument(&quot;v1&quot;, &quot;Production API&quot;, &quot;api/v1/spec.json&quot;),<br>    new ScalarDocument(&quot;v2-beta&quot;, &quot;Beta API&quot;, &quot;beta/openapi.json&quot;),<br>    new ScalarDocument(&quot;v3-dev&quot;, &quot;Development API&quot;, &quot;dev/{documentName}.json&quot;)<br>};<br>app.MapScalarApiReference(options =&gt; options.AddDocuments(documents));</pre><p>AddDocument metodundaki routePattern parametresi, OpenAPI dokümanının hangi URL yolunda sunulacağını özelleştirmeni sağlar. Eğer belirtilmezse, varsayılan olarak ayarlardaki global OpenApiRoutePattern değeri kullanılır. Bu desen içinde {documentName} yer tutucusu bulunabilir ve bu kısım doküman adıyla değiştirilir.</p><h4>Tasarım/Tema Desteği</h4><p>Scalar, geliştiricilere kullanıcı arayüzünü kendi marka kimliğine göre özelleştirme imkânı verir. Varsayılan tema seçeneklerinin ötesine geçerek <strong>kendi CSS/JS dosyalarını entegre edebilir</strong>, logo, font ve renk paletini kontrol edebilirsin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*URynOVJs4MRaw6IOa9e5ug.png" /></figure><p><strong>Hazır temaları kullanmak:</strong></p><pre>app.MapScalarApiReference(opt =&gt;<br>{<br>    opt.WithTitle(&quot;Okyanus Tonlarında API Dokümantasyonu&quot;)<br>       .WithTheme(ScalarTheme.BluePlanet);<br>});</pre><p><strong>Özelleştirilmiş CSS/JS kullanmak:</strong></p><pre>app.MapScalarApiReference(opt =&gt;<br>{<br>    opt.WithTitle(&quot;Intertech API Dokümantasyonu&quot;)<br>       .WithTheme(ScalarTheme.Default)<br>       .WithCustomCss(&quot;/assets/scalar/custom-style.css&quot;)<br>       .WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient);<br>});</pre><p>wwwroot/assets/scalar/custom-style.css</p><pre>body {<br>    font-family: &#39;Segoe UI&#39;, sans-serif;<br>    background-color: #1e1e2f;<br>    color: #e0e0e0;<br>}</pre><h4>Container ve Çoklu Ortamlarda Scalar Kullanımı</h4><p>Özellikle Docker ve Kubernetes gibi konteyner ortamlarında, API servisleriniz farklı portlarda çalışabilir. Scalar’ın MapScalarApiReference metodu, ortam değişkenleri ile portları dinamik olarak algılayabilir ve doğru OpenAPI endpoint’lerini otomatik oluşturur.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QxhVRvWEl3NukwHMELirEw.png" /></figure><pre>app.MapScalarApiReference(opt =&gt;<br>{<br>    List&lt;ScalarServer&gt; servers = new();<br>    string? httpsPort = Environment.GetEnvironmentVariable(&quot;ASPNETCORE_HTTPS_PORT&quot;);<br>    if (httpsPort != null)<br>        servers.Add(new ScalarServer($&quot;https://localhost:{httpsPort}&quot;));<br><br>    string? httpPort = Environment.GetEnvironmentVariable(&quot;ASPNETCORE_HTTP_PORT&quot;);<br>    if (httpPort != null)<br>        servers.Add(new ScalarServer($&quot;http://localhost:{httpPort}&quot;));<br><br>    opt.Servers = servers;<br>    opt.Title = &quot;Containerize API Dokümantasyonu&quot;;<br>    opt.ShowSidebar = true;<br>});</pre><p>Bu, çoklu servislerin bulunduğu karmaşık projelerde bile dokümantasyonun her zaman erişilebilir ve güncel kalmasını sağlar.</p><h4>Scalar Arayüzünü Otomatik Açmak</h4><p>launchSettings.json dosyasındaki launchUrl ayarını scalar olarak değiştirerek, uygulama çalıştığında otomatik olarak Scalar UI açılmasını sağlayabilirsiniz.</p><pre>&quot;launchUrl&quot;: &quot;scalar&quot;</pre><h4>Değerlendirme</h4><p>OpenAPI ile API’lerinizi standartlaştırmak artık neredeyse zorunlu bir gereklilik. Scalar ise bu dokümantasyonları modern, hızlı ve kullanıcı dostu şekilde sunarak geliştirici deneyimini üst seviyeye çıkarıyor.</p><p>Özellikle performans, mobil uyumluluk ve kolay özelleştirilebilirlik Scalar’ı cazip kılıyor. Container ortamlarında portları otomatik algılayabilmesi büyük projelerde konfor sağlıyor.</p><p>Bu sebeplerle, Swagger yerine Scalar’ı tercih etmek yeni nesil ASP.NET projeleri için sağlam bir seçenek olarak öne çıkıyor.</p><ul><li><a href="https://scalar.com/">Scalar - Document, Discover and Test APIs</a></li><li><a href="https://github.com/scalar/scalar/blob/main/integrations/aspnetcore/README.md">scalar/integrations/aspnetcore/README.md at main · scalar/scalar</a></li><li><a href="https://www.openapis.org/">OpenAPI Initiative - The OpenAPI Initiative provides an open source, technical community, within which industry participants may easily contribute to building a vendor-neutral, portable and an open specification for providing technical metadata for REST APIs - the &quot;OpenAPI Specification&quot; (OAS).</a></li><li><a href="https://guides.scalar.com/scalar/scalar-api-references/net-integration">.NET Integration</a></li><li><a href="https://codewithmukesh.com/blog/dotnet-swagger-alternatives-openapi/">Swagger is Dead? Here&#39;s the Alternative! - codewithmukesh</a></li><li><a href="https://www.linkedin.com/pulse/from-swagger-scalar-net-9-evolution-begins-venkat-prabhu-n-zkohc/">&quot;From Swagger to Scalar: The .NET 9 Evolution Begins&quot;</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d18875640af5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/intertechit/scalar-ile-net-api-dok%C3%BCmantasyonunda-yeni-d%C3%B6nem-d18875640af5">Scalar ile .NET API Dokümantasyonunda Yeni Dönem</a> was originally published in <a href="https://medium.com/intertechit">Intertech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Yeni Nesil Liderler için Yol Haritası: Management 3.0]]></title>
            <link>https://medium.com/intertechit/yeni-nesil-liderler-i%C3%A7in-yol-haritas%C4%B1-management-3-0-43d023251af8?source=rss----d21876bad59---4</link>
            <guid isPermaLink="false">https://medium.com/p/43d023251af8</guid>
            <category><![CDATA[management]]></category>
            <category><![CDATA[çeviklik]]></category>
            <category><![CDATA[management30]]></category>
            <category><![CDATA[agile]]></category>
            <category><![CDATA[çevik]]></category>
            <dc:creator><![CDATA[Sercan AĞRI]]></dc:creator>
            <pubDate>Thu, 15 May 2025 07:50:01 GMT</pubDate>
            <atom:updated>2025-05-15T07:50:01.761Z</atom:updated>
            <content:encoded><![CDATA[<p>Günümüz iş dünyasındaki değişim hızı sürekli bir adaptasyonu gerektiriyor ve bu dinamik ortamda liderlik anlayışları da hızla evriliyor. Artık liderlerden sadece işleri ve ekipleri etkin bir şekilde yönetmeleri değil, aynı zamanda ekiplerinin önündeki engelleri kaldırmaları, çalışanların mutluluğunu ve iş verimliliğini en üst düzeye çıkarmaları bekleniyor. Geleneksel yönetim yaklaşımlarının ötesine geçilmesi gereken bu yeni dönemde, Management 3.0 devreye giriyor ve yeni nesil liderler için kapsamlı bir rehber sunuyor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*327FXIYDXA__UO15X5qbSg.png" /></figure><h4>Management 3.0 Nedir?</h4><p>Management 3.0, Jurgen Appelo tarafından 2010 yılında geliştirilmiş, son yıllarda ülkemizde popülerliğini arttırmaya başlamış modern bir liderlik ve yönetim modelidir. Bu model, çalışanları organizasyonun en önemli varlığı olarak görüyor ve onların mutluluğunu, motivasyonunu ve etkinliğini ön planda tutuyor.</p><p>Management 3.0, geleneksel yönetim anlayışlarının aksine, daha fazla iş birliği ve insan odaklı bir yaklaşımı teşvik ediyor. Bu model, çalışanların potansiyellerini en iyi şekilde kullanmalarını sağlamak amacıyla liderlerin destekleyici ve yönlendirici bir rol üstlenmesini vurguluyor.</p><p>Management 3.0’ın sağladığı en büyük avantajlardan biri, ekiplerin kendi kendine yönetilme ve problem çözme becerilerini geliştirmesidir. Özellikle çevik organizasyonlarda, bu modelin getirdiği özerklik ve destekleyici yaklaşımlar, ekiplerin daha yaratıcı ve verimli sonuçlar üretmelerine olanak tanıyor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/945/1*DZyPOb05T01yE5jAm9Hoag.png" /><figcaption><em>Jurgen Appelo</em></figcaption></figure><h4>Management 1.0 ve 2.0’ın Ötesinde: Neden Management 3.0?</h4><p>Yönetim anlayışlarını değerlendirirken, Management 1.0 ve 2.0 modellerine göz atmak faydalı olacaktır.</p><p>İş hayatımda Management 1.0, 2.0 ve 3.0 yaklaşımlarını benimsemiş farklı liderlerle çalışma şansım oldu. Bu liderlik tarzlarının ekip içindeki etkileşimleri, sorumluluk alma biçimlerini ve karar süreçlerini nasıl etkilediğini bizzat deneyimledim.</p><p><strong>Management 1.0</strong>: Geleneksel yönetim tarzıdır. Katı bir hiyerarşik yapı vardır; lider emir verir, çalışan uygular. Lider başarıyı kendisine, başarısızlığı ise çalışanlara yazar. İnsanlar birer “kaynak” olarak görülür. Bu yaklaşımda inisiyatif yoktur, çalışanlar sadece verilen işi yapar. Yaratıcılığı ve katılımı körelten bir sistemdir.</p><p><strong>Management 1.0 </strong>yaklaşımına yakın bir yöneticimle çalıştığım dönemde, ekip içindeki en basit kararların bile mutlaka onun onayından geçmesi gerekiyordu. Hatta sadece takım içinde kalacak bir takım anlaşması afişinde kullanılan fonta ve metne dahi müdahale ettiğini hatırlıyorum. O an içimden şöyle geçirmiştim: “Bu kadar küçük bir konuda bile bu kadar kontrol varsa, acaba bu sadece bana mı özel bir tutum, yoksa tüm takıma karşı aynı şekilde mi davranılıyor?” Bu sorgulama bile aslında başlı başına o liderlik yaklaşımının yarattığı güvensizlik ortamının bir göstergesiydi.</p><p><strong>Management 2.0</strong>: Modern araç ve yöntemler (örneğin performans değerlendirme sistemleri, anketler, ödüllendirme sistemleri vb.) devreye girmiştir. Ancak bunlar genellikle yüzeyde kalır. Çalışanlara danışılıyor gibi görünse de, gerçek güç yine yöneticidedir. Yani “görüş alınıyor” ama “karar alma” yetkisi devredilmez. Bu modelde lider, eski hiyerarşiyi korur ama modern süslemelerle kaplar.</p><p><strong>Management 2.0 </strong>yaklaşımına yakın bir liderle çalıştığım dönemde,<strong> </strong>kendimi daha rahat hissettiğim dönemler oldu, özellikle işler yolunda giderken ve kararlarda daha fazla söz hakkım olduğunda. Fikirlerim değer buluyordu ve ekip olarak daha açık bir iletişim içindeydik. Ancak işler karmaşıklaşmaya başladığında ve bir kriz anı yaşandığında, bir anda karar mekanizmasından dışlanmış hissediyordum. Stratejiyle ilgili önemli hatalar fark ettiğimde, bu durumu dile getirdiğimde bana çoğu zaman “Bu liderin sorumluluğunda” deniyordu. Takım olarak doğru yolda olmadığımızı, uçuruma doğru gittiğimizi hissettiğimizde bile, tek başına liderin kararlarına odaklanılmak zorunda kalıyorduk. Bu deneyim, aslında görünürde daha modern ve katılımcı bir yapının, temelde yine liderin kontrolünde olduğunu bana gösterdi.</p><p><strong>Management 3.0</strong>: Gerçek bir zihniyet dönüşümünü temsil eder. Yönetim sadece yöneticinin işi değildir; herkesin katkısı önemlidir. Liderler, sistemi yönetir; insanları değil. Ekiplerin kendi kararlarını verebilecekleri bir ortam kurulur. Yetki devri yapılır, güven ortamı yaratılır. Yaratıcılık, iş birliği ve sürekli gelişim teşvik edilir.</p><p><strong>Management 3.0 </strong>yaklaşımına sahip bir liderle çalıştığımda ise tamamen farklı bir deneyim yaşadım. Lider, karar alma süreçlerine katılımı teşvik ediyor ve hata yapma konusunda güvenli bir ortam sunuyordu. Bu ortamda hatalarım beni korkutmak yerine, onlardan öğrenebileceğimi ve gelişebileceğimi hissettim. Zamanla, belirli konularda özgüvenim arttı ve kendi başıma bağımsız kararlar alabileceğim bir profesyonel ortamda çalışmak, hem benim hem de ekip arkadaşlarımın gelişimini doğrudan destekleyen bir deneyim oldu.</p><h4><strong>Agile ile Management 3.0&#39;ın Bağı</strong></h4><p>Agile ve Management 3.0 arasında güçlü bir bağ bulunuyor, çünkü her iki yaklaşım da aynı temel hedeflere yöneliyor: özerklik, iş birliği ve sürekli gelişim. Agile, ürün geliştirme süreçlerinde çevikliği, adaptasyonu ve hızlı geri bildirim almayı vurgularken; Management 3.0, bu çevikliği organizasyon genelinde bir kültür haline getirmeyi amaçlar. Agile, daha çok pratikteki yöntemlere odaklanırken, Management 3.0 insan odaklı bir liderlik anlayışı sunarak ekiplerin potansiyellerini en üst düzeye çıkarmayı hedefler. Bu iki yaklaşım bir araya geldiğinde, organizasyonlar sadece daha çevik değil, aynı zamanda daha insan odaklı, katılımcı ve sürdürülebilir bir iş ortamı yaratabilirler. Ekiplerin kendi kararlarını alabilmesi, özgürce fikir paylaşabilmesi ve sürekli gelişime odaklanabilmesi için bu iki yaklaşım mükemmel bir uyum sağlar.</p><h4>Management 3.0’ın Temel İlkeleri</h4><p>Management 3.0, çalışanları ve organizasyonları daha etkili ve verimli bir şekilde yönetmek için beş temel ilkeye dayanır. Bu ilkeler, organizasyonel başarıyı destekleyen ve ekiplerin en yüksek potansiyeline ulaşmasını sağlayan stratejileri içerir:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/556/1*Ymp_UweDfV1noD3dtwQPaA.png" /></figure><p>· <strong>İnsanları ve Etkileşimlerini Kapsama</strong><br> Çalışanları işin içine katmak ve onların birbirleriyle etkileşimlerini artırmak, başarılı bir organizasyonun temel taşlarındandır. İnsanların aktif bir şekilde iş sürecine dahil olmaları ve aralarındaki etkileşimlerin güçlendirilmesi, hem motivasyonu hem de iş verimliliğini artırır. Çalışanların fikirlerinin değer görmesi ve saygı duyulması önemlidir. Birlikte çalışma şansı bulduğum ekiplerde, ekip üyelerinin katkılarının takdir ediliyor olmasının onların motivasyonunu ve bağlılıklarını arttırdığını gözlemledim. Çalışanlara, kendi fikirlerini ifade etme ve bu fikirlerin organizasyonel süreçlerde yer bulmasını sağlama fırsatı vermek, onların işlerine daha fazla bağlılık göstermelerini sağlıyor.</p><p>· <strong>Sistemi İyileştirme</strong><br> Management 3.0, sadece tek bir takımın değil, sistemde yer alan herkesin iyileştirilmesini hedefler. “Sistem” kelimesinin anlamı, karmaşık ve uyumlu bir yapı olarak görülmelidir. Management 3.0, organizasyonları karmaşık uyumlu sistemler olarak kabul eder. Bu sistemler, birçok bileşenin birbirleriyle etkileşimde bulunduğu ve davranışlarının her zaman öngörülebilir olmadığı yapılardır. İyileştirme, bu sistemlerin sürekli olarak gelişmesini sağlar. Bu ilkeye göre, başarılı olmak için sürekli denemeler yapmalı, denemeler gerçekleştirmeli ve bu deneyimlerden öğrenmeliyiz.</p><p>· <strong>Tüm Müşterileri Memnun Etme</strong><br> Müşteriler sadece dış müşterilerle sınırlı değildir. Management 3.0, tüm sistemdeki kişileri müşteri olarak görür. Ekip üyeleri, diğer takımlar, ve paydaşlar da müşteri olarak kabul edilir. Amacımız, tüm bu müşterilerin memnuniyetini sağlamak ve onlara değerli hizmetler sunmaktır. Müşteri memnuniyeti, organizasyonun genel başarısı için kritik öneme sahiptir.</p><p>· <strong>İnsanların Değil Sistemin Yönetilmesi</strong><br> İnsanların davranışlarını değiştirmek zordur; ancak ortamı değiştirdiğinizde, insanlar bu yeni ortama uyum sağlama eğilimi gösterirler. Management 3.0, insanların kendilerini yönetebileceği bir ortam yaratmayı amaçlar. Bu, liderlerin, organizasyonel sistemi beslemek ve yönlendirmekle yükümlü olduğu anlamına gelir. Sistemi iyileştirmek ve desteklemek, çalışanların kendi kendilerini yönetmelerine olanak tanır.</p><p><strong>· İş birliği ile Çalışma</strong><br> Hızla değişen ve karmaşık bir dünyada, bireysel fikirler tek başına yeterli olmayabilir. İş birliği, başarılı bir iş ortamının temelidir. Bu ilkeye göre, ekip üyeleri, liderler ve diğer paydaşlar birlikte çalışmalı ve ortak çözümler üretmelidir. Yönetici olarak, iş birliğini teşvik eden ve destekleyen bir sistem yaratmalısınız. Bu ilkeye yardımcı olabilecek bazı yöntemler şunlardır: Takım Anlaşması Kanvası ve Takım Yetkinlik Matrisi. Bu araçlar, ekip içindeki iş birliğini artırır ve ortak hedeflere ulaşmayı kolaylaştırır. <strong><em>Önümüzdeki yazılarda bu teknikleri anlatıyor olacağım.</em></strong></p><h4><strong>Management 3.0 Kullanım Örnekleri</strong></h4><p>Management 3.0, birçok şirket tarafından benimsenmiş ve etkili sonuçlar elde edilmiştir. Örneğin, Brezilyalı şirket AmbevTech, Management 3.0’ı benimsedikten bir yıl sonra ülkede çalışmak için en iyi yer haline gelmiş ve müşteri memnuniyetini %78 oranında artırmıştır. İspanyol yazılım şirketi Keepler de Management 3.0 kavramlarını uyguladıktan sonra kendi kendine yeten ekipler oluşturma konusunda başarılı olmuştur. <strong><em>Bu örneklerin detaylı anlatımlarının olduğu blog yazılarını paylaşacağım.</em></strong></p><h4><strong>Management 3.0’ı Öğrenme İçin Kaynak Önerilerim</strong></h4><p>Management 3.0’ın prensiplerini daha iyi anlamak ve uygulamak isteyenler için bazı kaynakları önereceğim:</p><ul><li><strong>Ana Kaynak:</strong> <em>“Management 3.0: Leading Agile Developers, Developing Agile Leaders”</em>, Jurgen Appelo’nun kaleme aldığı bu kitap, Management 3.0 modelinin temel ilkelerini ve uygulama stratejilerini kapsamlı bir şekilde ele alır. Kitap, liderlerin ve organizasyonların bu modern yönetim yaklaşımını nasıl benimseyebileceğine dair pratik bilgiler ve örnekler sunar. Yönetim tarzınızı dönüştürmek ve ekiplerinizin potansiyelini en üst düzeye çıkarmak için mükemmel bir başlangıçtır.</li><li><strong>Web Sitesi: </strong><br> <a href="https://management30.com/">https://management30.com/</a> : Management 3.0’ın resmi web sitesi, konuyu anlamak ve uygulamak için zengin bir içerik sunar. Burada blog yazıları, video röportajlar, interaktif webinar’lar ve başarı hikayeleri gibi kaynaklar bulabilirsiniz. Ayrıca, güncel gelişmeleri takip etmek ve uygulamaları hakkında daha fazla bilgi edinmek için bu siteyi düzenli olarak ziyaret edebilirsiniz.</li><li><strong>Örnek Vakalar</strong>:<br> <a href="https://management30.com/experience/case-studies/keepler/">https://management30.com/experience/case-studies/keepler/</a> <a href="https://management30.com/experience/case-studies/ambevtech-technological-hub-brazil/">https://management30.com/experience/case-studies/ambevtech-technological-hub-brazil/</a></li><li><strong>Youtube Kanalı: </strong>Management 3.0’ın resmi Youtube kanalı, konuyla ilgili çeşitli video içerikleri sunar.<br> <a href="https://www.youtube.com/watch?v=T9d8w-OG-Fk&amp;list=PLHXDFUoljQxByuXvajagqmmPjmERFIy0f">https://www.youtube.com/watch?v=T9d8w-OG-Fk&amp;list=PLHXDFUoljQxByuXvajagqmmPjmERFIy0f</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=43d023251af8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/intertechit/yeni-nesil-liderler-i%C3%A7in-yol-haritas%C4%B1-management-3-0-43d023251af8">Yeni Nesil Liderler için Yol Haritası: Management 3.0</a> was originally published in <a href="https://medium.com/intertechit">Intertech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Global Uygulamalarda Doğru Zaman Yönetimi]]></title>
            <link>https://medium.com/intertechit/global-uygulamalarda-do%C4%9Fru-zaman-y%C3%B6netimi-c5d43d33c67d?source=rss----d21876bad59---4</link>
            <guid isPermaLink="false">https://medium.com/p/c5d43d33c67d</guid>
            <category><![CDATA[datetime]]></category>
            <category><![CDATA[global-application]]></category>
            <category><![CDATA[globalization]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[timezone-difference]]></category>
            <dc:creator><![CDATA[Cihat Solak]]></dc:creator>
            <pubDate>Tue, 22 Apr 2025 06:01:54 GMT</pubDate>
            <atom:updated>2025-04-22T06:01:54.814Z</atom:updated>
            <content:encoded><![CDATA[<h4>Time Handling Best Practices for Global-Scale Applications</h4><p>Tarih ve saat verilerini yönetmek, uygulamalarda doğru zaman damgaları, tarihsel kayıtlar ve zaman dilimleri gibi hassas bilgilerin işlenmesi açısından kritik bir rol oynar. Bu tür işlemler için C#’ta iki ana veri tipi vardır: DateTime ve DateTimeOffset. Her ikisi de tarihi ve zamanı temsil eder, ancak zaman dilimleri ve saat farkları konusunda farklı yaklaşımlar sunar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8BfSZHNWCTnW6ppW7lkM0w.jpeg" /><figcaption>DateTimeOffset, zaman dilimi farklarını doğru şekilde yöneterek global uygulamalarda zaman uyumsuzluklarını önler.</figcaption></figure><h4>DateTime Nedir?</h4><p>DateTime, hem tarih hem de saat bilgilerini depolayan bir veri türüdür. Kullanıcının saat dilimini belirtmesine bağlı olarak, <strong>UTC</strong> (Koordinatlı Evrensel Zaman) veya <strong>yerel saat </strong>olarak tanımlanabilir. Ancak DateTime, kendisiyle ilişkili bir zaman dilimi bilgisi içermez. Bu durum, farklı zaman dilimlerinde çalışırken veri uyumsuzluklarına ve karışıklıklara neden olabilir.</p><pre>DateTime now = DateTime.Now;            // Yerel zaman<br>DateTime utcNow = DateTime.UtcNow;      // UTC zaman<br>DateTime specificDate = new DateTime(2023, 10, 29, 14, 30, 0); // Belirli bir tarih-saat</pre><ul><li>DateTime.Now: Bulunduğunuz yerel saat diliminde anlık zamanı alır.</li><li>DateTime.UtcNow: UTC saatine göre anlık zamanı alır.</li></ul><p>DateTime.Now ve DateTime.UtcNow arasındaki fark, tarih ve saat bilgilerinin hangi saat dilimine göre verildiğidir:</p><ul><li><strong>DateTime.Now</strong>: Sistemin yerel saat dilimine göre geçerli tarih ve saati verir. Bulunduğunuz coğrafi konuma göre saati belirler, yani <strong>bilgisayarın saat dilimi ayarlarını kullanır.</strong></li><li><strong>DateTime.UtcNow</strong>: UTC (Coordinated Universal Time) saat dilimine göre tarih ve saati verir. <strong>UTC, dünyada herkesin aynı referans noktası olarak kabul ettiği saat dilimidir</strong> <strong>ve yerel saat diliminden bağımsızdır.</strong> Örneğin, Türkiye&#39;deki DateTime.Now ile UTC arasındaki fark normalde yaz saati uygulanmıyorsa +3 saat olur.</li></ul><h4>UtcNow Neye Göre Belirleniyor?</h4><p>DateTime.UtcNow, bilgisayarın veya sunucunun dahili saatini UTC referans noktasına göre alır. Sistem zamanı internetten veya yerel bir sunucudan otomatik olarak senkronize ediliyorsa, bu saat de düzenli olarak UTC&#39;ye göre güncellenir. UTC saat dilimi dünya genelinde standart kabul edildiğinden, farklı saat dilimlerindeki sistemlerin birbirleriyle uyumlu çalışmasını sağlar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/728/1*umfkJFYE3jJTmN3jlw6Xxw.png" /><figcaption>DateTimeOffset, UTC zamanını ve saat dilimi bilgisini aynı anda saklayarak daha doğru zaman dönüşümleri sağlar.</figcaption></figure><h4>DateTimeOffset Nedir?</h4><p>DateTimeOffset, tarih ve saat bilgisini bir zaman dilimi ofsetiyle (UTC&#39;ye göre fark) birlikte saklar. Böylece belirli bir saatin UTC&#39;ye göre saat farkını içerir. DateTimeOffset, özellikle zaman dilimlerinin farklı olduğu uygulamalarda (örneğin uluslararası projeler) veri uyumluluğunu korumak için daha güvenilir bir seçenek sunar.</p><pre>DateTimeOffset now = DateTimeOffset.Now;              // Yerel zaman ve ofset<br>DateTimeOffset utcNow = DateTimeOffset.UtcNow;        // UTC zaman ve ofset 0<br>DateTimeOffset specificDateWithOffset = new DateTimeOffset(2023, 10, 29, 14, 30, 0, TimeSpan.FromHours(3)); // +03:00 ofseti ile tarih-saat</pre><ul><li>DateTimeOffset.Now: Anlık zamanı ve UTC&#39;ye göre ofsetini alır.</li><li>DateTimeOffset.UtcNow: UTC zamanını ve ofsetini alır.</li></ul><h4>DateTime ve DateTimeOffset Karşılaştırması</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2KoV2EtqjtEOY2isayXOdA.png" /></figure><h4>Ne Zaman Hangi Tür Kullanılmalı?</h4><p><strong>Yerel Tarih ve Saat Gerektiğinde: </strong>Sadece yerel bir saat ve tarihe ihtiyaç duyuyorsanız (örneğin, takvimde gün seçimi) DateTime kullanımı yeterli olacaktır.</p><p><strong>Uluslararası Zaman Dilimleriyle Çalışırken</strong>: Farklı bölgelerde zaman dilimi farklarını yönetmek istiyorsanız DateTimeOffset tercih edilmelidir.</p><h4>Kodlama Örnekleri ve Senaryolar</h4><p><strong>Örnek 1: UTC Zamanı ile İşlem Yapma</strong></p><p>UTC zamanına göre bir tarih-saat saklamak istediğinizde DateTime veya DateTimeOffset türleri ile nasıl çalışabileceğinizi görelim:</p><pre>// DateTime ile UTC Zaman<br>DateTime utcTime = DateTime.UtcNow;<br><br>// DateTimeOffset ile UTC Zaman<br>DateTimeOffset utcTimeOffset = DateTimeOffset.UtcNow;</pre><p><strong>Örnek 2: Zaman Dilimleri Arasında Fark Hesaplama</strong></p><p>İki tarih-saat arasındaki farkı hesaplamak DateTime ve DateTimeOffset ile mümkündür, ancak DateTimeOffset daha doğru sonuç verir çünkü ofset bilgilerini korur.</p><pre>DateTimeOffset startTime = new DateTimeOffset(2023, 10, 29, 10, 0, 0, TimeSpan.FromHours(-5));<br>DateTimeOffset endTime = new DateTimeOffset(2023, 10, 29, 15, 0, 0, TimeSpan.FromHours(0));<br><br>// Fark hesaplama<br>TimeSpan difference = endTime - startTime;<br>Console.WriteLine($&quot;Fark: {difference.TotalHours} saat&quot;); // Çıktı: 10 saat</pre><h4>DateTimeOffset ve DateTime Seçiminde Önemli Noktalar</h4><p><strong>Global Uygulamalar</strong>: Kullanıcılar farklı zaman dilimlerinde ise DateTimeOffset tercih edilmelidir.</p><p><strong>Yerel Uygulamalar</strong>: Sadece yerel zaman gereksinimlerinde DateTime kullanımı daha basit ve performanslı olabilir.</p><p><strong>Zaman Dilimi Uyumsuzluklarından Kaçınma</strong>: Farklı saat dilimlerinde çalışan ekipler veya kullanıcılar için, zaman dilimi ofsetini içeren DateTimeOffset daha az hata ve uyuşmazlık sağlar.</p><h4>Time Zone Desteği ile Göreli Zaman Gösterimi</h4><p>Global uygulamalarda tarih/saat verilerinin tutarlı yönetimi için UTC formatı kullanılmalıdır. Ürün eklenme zamanı gibi bilgileri gösterirken, UTC’de saklanan veriler kullanıcı saat dilimine çevrilerek gösterilmelidir.</p><p>JavaScript ile kullanıcının saat dilimi bilgisi alınabilir:</p><pre>const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;</pre><p>Bu bilgi her istekle birlikte örneğin bir HTTP header olarak backend’e gönderilmelidir. Aşağıdaki örnek, gelen Time-Zone bilgisine göre göreli zaman hesaplaması yapar:</p><pre>[HttpGet(&quot;product-time-ago&quot;)]<br>public IActionResult GetProductTimeAgo([FromHeader(Name = &quot;Time-Zone&quot;)] string timeZoneId)<br>{<br>    DateTime createdAtUtc = new DateTime(2025, 4, 19, 10, 0, 0, DateTimeKind.Utc);<br><br>    TimeZoneInfo timeZone;<br>    try<br>    {<br>        timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);<br>    }<br>    catch<br>    {<br>        timeZone = TimeZoneInfo.Utc;<br>    }<br><br>    DateTime userNow = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, timeZone);<br>    DateTime userCreatedAt = TimeZoneInfo.ConvertTimeFromUtc(createdAtUtc, timeZone);<br>    var diff = userNow - userCreatedAt;<br><br>    string result = diff.TotalMinutes &lt; 1 ? &quot;az önce eklendi&quot;<br>                 : diff.TotalMinutes &lt; 60 ? $&quot;{(int)diff.TotalMinutes} dk önce eklendi&quot;<br>                 : diff.TotalHours &lt; 24 ? $&quot;{(int)diff.TotalHours} saat önce eklendi&quot;<br>                 : $&quot;{(int)diff.TotalDays} gün önce eklendi&quot;;<br><br>    return Ok(result);<br>}</pre><p>Bu yapı sayesinde zaman bilgisi, her kullanıcıya kendi lokal saatine göre doğru biçimde gösterilir.</p><h4>Sonuç</h4><p>DateTime ve DateTimeOffset, doğru senaryolarda kullanıldıklarında güçlü ve işlevsel veri türleridir. Yerel bir saati temsil etmek için DateTime, zaman dilimleriyle uyumlu veriler oluşturmak ve saklamak için DateTimeOffset tercih edilmelidir. İki tür arasında doğru tercihi yapmak, uygulamanızın zaman verisi yönetimindeki doğruluğunu ve uyumluluğunu artırır.</p><ul><li><a href="https://learn.microsoft.com/en-us/dotnet/standard/datetime/">Dates, times, and time zones - .NET</a></li><li><a href="https://stackoverflow.com/questions/8589014/how-to-change-time-zone-for-an-asp-net-application">How to change time zone for an asp.net application</a></li><li><a href="https://www.meziantou.net/convert-datetime-to-user-s-time-zone-with-server-side-blazor-time-provider.htm">Convert DateTime to user&#39;s time zone with Blazor in .NET 8 - Gérald Barré</a></li><li><a href="https://www.bytehide.com/blog/datetime-now-vs-datetime-utcnow-csharp">C# DateTime.Now vs DateTime.UtcNow: Differences and Use Cases</a></li><li><a href="https://blog.nimblepros.com/blogs/time-provider-time-zones/#sq_hqsw4lpshq">Customize Application Time Zone with TimeProvider</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c5d43d33c67d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/intertechit/global-uygulamalarda-do%C4%9Fru-zaman-y%C3%B6netimi-c5d43d33c67d">Global Uygulamalarda Doğru Zaman Yönetimi</a> was originally published in <a href="https://medium.com/intertechit">Intertech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Roslyn: .NET için Modern Derleyici Platformu]]></title>
            <link>https://medium.com/intertechit/roslyn-net-i%C3%A7in-modern-derleyici-platformu-6d15b10c1477?source=rss----d21876bad59---4</link>
            <guid isPermaLink="false">https://medium.com/p/6d15b10c1477</guid>
            <category><![CDATA[code-analysis]]></category>
            <category><![CDATA[net-compiler-platform]]></category>
            <category><![CDATA[roslyn]]></category>
            <category><![CDATA[syntax-tree]]></category>
            <category><![CDATA[csharp-compiler]]></category>
            <dc:creator><![CDATA[Cihat Solak]]></dc:creator>
            <pubDate>Mon, 24 Mar 2025 07:54:43 GMT</pubDate>
            <atom:updated>2025-03-24T07:54:43.223Z</atom:updated>
            <content:encoded><![CDATA[<h3>Roslyn: .NET için Modern Derleyici Platformu</h3><h4>Roslyn: The Modern Compiler Platform for .NET</h4><p>Roslyn, Microsoft’un .NET uygulamaları için geliştirdiği, güçlü ve esnek bir derleyici platformudur. .NET için Roslyn projesi, sadece bir derleyici değil, aynı zamanda C# ve Visual Basic (VB.NET) dillerinin işlenmesini ve analiz edilmesini sağlayan geniş bir API seti sunar. Bu özellikler sayesinde, geliştiriciler derleyici seviyesinde analiz ve dönüştürme işlemlerini doğrudan projelerinde gerçekleştirebilirler.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2eS2_1mij4KcKJn0m2OMug.jpeg" /><figcaption>Roslyn provides access to the code model created by compilers, enabling smarter development tools and IDE features.</figcaption></figure><h3>Roslyn Nedir?</h3><p>Roslyn, C# ve VB.NET dillerini derlemek için kullanılan açık kaynaklı bir .NET Compiler Platformudur. Geliştiricilere, derleme sürecinin her aşamasına erişim sağlayarak, dil düzeyinde analiz ve dönüştürme işlemlerini mümkün kılar. Roslyn, hem derleme işlemi için gerekli araçları sağlar, hem de C# ve VB.NET dil yapısına erişim sunarak kod analizi, yeniden yazma ve oluşturma gibi işlemleri mümkün hale getirir.</p><h4>Roslyn, şu bileşenlerden oluşur:</h4><ul><li><strong>Parser</strong>: Kodları analiz eder ve kodun yapısını oluşturan sözdizimi ağacını (syntax tree) çıkarır.</li><li><strong>Semantic Model</strong>: Kodun anlamsal yapısını oluşturur ve sembol bilgilerini sağlar.</li><li><strong>Code Generation</strong>: Kodun yürütülebilir dosyalar (DLL veya EXE) haline dönüştürülmesini sağlar.</li><li><strong>Compilation API</strong>: Derleme işlemlerini yönetir ve özelleştirme seçenekleri sunar.</li></ul><h3>Roslyn’in Özellikleri</h3><p>Roslyn’in derleyici ve analiz özellikleri, hem derleme sürecinde hem de geliştirme ortamında kullanıcılara esneklik sağlar.</p><p><strong>a. Syntax Tree (Sözdizimi Ağacı)</strong><br>Roslyn, her bir kod bloğunu sözdizimsel düğümlere ayırarak bir syntax tree oluşturur. Bu sayede geliştiriciler, kodun yapısal analizi için her bir ifadeye, deyime ve öğeye erişebilir.</p><p><strong>Örnek:</strong></p><pre>using Microsoft.CodeAnalysis.CSharp;<br>using Microsoft.CodeAnalysis;<br><br>SyntaxTree tree = CSharpSyntaxTree.ParseText(&quot;int x = 10;&quot;);<br>var root = tree.GetRoot();<br>Console.WriteLine(root.ToString()); // int x = 10;</pre><p><a href="https://www.nuget.org/packages/microsoft.codeanalysis.csharp/">Microsoft.CodeAnalysis.CSharp 4.11.0</a></p><p><strong>b. Semantic Model (Anlamsal Model)</strong><br>Anlamsal model, bir kodun sözdizimsel yapısının ötesine geçerek değişken, tür ve metot gibi semboller hakkında bilgi sağlar. Bu model, değişkenlerin kapsamı, tip bilgisi, metot çağrıları ve diğer dil özellikleri hakkında detaylı bilgi sunar.</p><p><strong>c. Code Analysis (Kod Analizi)</strong><br>Roslyn, statik kod analizi yapabilme yeteneği sunar. Bu sayede kod kalitesini artırmak, potansiyel hataları yakalamak ve en iyi uygulamaları sağlamak için analiz işlemleri yapılabilir.</p><p><strong>d. Refactoring (Kod Yeniden Yapılandırma)</strong><br>Roslyn, IDE’lerde kodu yeniden düzenleme (refactoring) işlemleri için kullanılabilir. Örneğin, bir değişken adını değiştirmek veya bir metot çağrısını daha okunaklı hale getirmek gibi işlemler Roslyn ile yapılabilir.</p><h3>Roslyn ile Derleme Süreci</h3><p>Roslyn, bir C# veya VB.NET kodunu derlemek için aşağıdaki adımları takip eder:</p><ol><li><strong>Kodun Parse Edilmesi (Parse)</strong><br>Kod, parse edilir ve bir syntax tree oluşturulur. Bu aşamada, kodun yapısal hataları tespit edilebilir.</li><li><strong>Anlamsal Modelin Oluşturulması (Semantic Analysis)</strong><br>Syntax tree üzerinde bir semantic analysis yapılır ve semboller tanımlanır. Kodun anlamı değerlendirilir ve tür bilgisi gibi detaylar eklenir.</li><li><strong>Optimizasyon ve Dönüştürme</strong><br>Kod optimize edilir ve derleme için uygun bir ara kod (intermediate code) haline getirilir.</li><li><strong>Yürütülebilir Kod Üretimi (Emit)</strong><br>Kod, yürütülebilir bir biçime (örneğin, bir DLL veya EXE dosyasına) dönüştürülür.</li></ol><p>Bu süreç, Microsoft.CodeAnalysis namespace’i altındaki Compilation sınıfları ile yönetilebilir ve özelleştirilebilir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QUdqiGDjEusTdjm8JOqlQQ.png" /><figcaption>The .NET Compiler Platform SDK exposes the C# and Visual Basic compilers’ code analysis to you as a consumer by providing an API layer that mirrors a traditional compiler pipeline.</figcaption></figure><h3>Roslyn Kullanım Senaryoları</h3><p><strong>a. IDE İçin IntelliSense ve Kod Tamamlama</strong><br>Roslyn, Visual Studio gibi IDE’lerde IntelliSense ve kod tamamlama özellikleri için kullanılmaktadır. Syntax tree ve semantic model sayesinde, kod yazarken anında önerilerde bulunur ve olası hataları gösterir.</p><p><strong>b. Kod Analiz Araçları</strong><br>Roslyn, statik kod analizi araçları oluşturmak için mükemmel bir altyapı sunar. Örneğin, kurumsal bir uygulamada belirli güvenlik standartlarının uygulanıp uygulanmadığını analiz eden özel bir araç geliştirebilir.</p><p><strong>c. Refactoring (Kod Yeniden Düzenleme)</strong><br>IDE’de kod yeniden düzenleme işlemleri yapılırken, Roslyn’in API’leri ile sınıf adlarının değiştirilmesi, metotların yeniden adlandırılması gibi işlemler kolayca gerçekleştirilebilir.</p><p><strong>d. Kendi Derleyici ve Analiz Araçlarınızı Geliştirme</strong><br>Roslyn, tamamen özelleştirilebilir bir derleyici platformu olduğundan, kendi kod dönüştürme veya analiz araçlarınızı geliştirmek için idealdir.</p><h3>Örnek: Roslyn ile Basit Kod Analizi</h3><p>Aşağıdaki örnekte, Roslyn kullanarak basit bir statik kod analizi yapacağız. Bu analiz, tüm for döngülerinde int türünde bir sayaç kullanıldığını kontrol eder.</p><pre>using Microsoft.CodeAnalysis;<br>using Microsoft.CodeAnalysis.CSharp;<br>using Microsoft.CodeAnalysis.CSharp.Syntax;<br>using System.Linq;<br><br>class Program<br>{<br>    static void Main()<br>    {<br>        var code = @&quot;<br>            using System;<br>            class Sample<br>            {<br>                void Test()<br>                {<br>                    for (int i = 0; i &lt; 10; i++) { Console.WriteLine(i); }<br>                }<br>            }&quot;;<br><br>        SyntaxTree tree = CSharpSyntaxTree.ParseText(code);<br>        var root = tree.GetRoot();<br><br>        var forStatements = root.DescendantNodes().OfType&lt;ForStatementSyntax&gt;();<br><br>        foreach (var forStatement in forStatements)<br>        {<br>            var declaration = forStatement.Declaration;<br>            if (declaration.Type.ToString() != &quot;int&quot;)<br>            {<br>                Console.WriteLine(&quot;Hata: Sayaç tipi &#39;int&#39; değil.&quot;);<br>            }<br>        }<br>    }<br>}</pre><p>Bu kod, for döngüsündeki sayaç değişkeninin int türünde olup olmadığını kontrol eder ve farklı bir tür kullanıldığında hata mesajı verir.</p><h3>Roslyn’in Avantajları</h3><ul><li><strong>Açık Kaynak</strong>: Roslyn, GitHub’da açık kaynak olarak sunulmaktadır, bu sayede geliştiriciler tarafından genişletilebilir ve özelleştirilebilir.</li><li><strong>IDE Entegrasyonu</strong>: Visual Studio gibi popüler IDE’lere entegre edilmiştir, bu da kod yazma deneyimini geliştirir.</li><li><strong>Esneklik</strong>: Syntax ve semantic analiz yapıları sayesinde, farklı kod analizleri ve kod dönüştürme işlemleri yapılabilir.</li><li><strong>Yüksek Performans</strong>: Roslyn, yüksek performans gereksinimlerini karşılayacak şekilde optimize edilmiştir.</li></ul><h4>Roslyn ile İleri Seviye Kod Analizi ve Dönüştürme</h4><p>Roslyn, sadece basit analizler için değil, aynı zamanda daha karmaşık kod analizleri ve kod dönüştürmeleri için de kullanılabilir. Örneğin:</p><ul><li><strong>Güvenlik Analizleri</strong>: Belirli bir kod parçasının güvenlik standartlarına uygun olup olmadığını denetlemek.</li><li><strong>Kendi Dil Özelliklerinizi Eklemek</strong>: C# veya VB.NET dil özelliklerini genişletmek ve kendi özel dil kurallarınızı uygulamak.</li></ul><h4>Sonuç</h4><p>Roslyn, modern .NET uygulamaları için güçlü ve esnek bir derleyici platformudur. Geliştiricilere, derleyici düzeyinde kontrol sağladığı için kod analizinden kod dönüştürmeye, hata denetiminden performans analizine kadar geniş bir yelpazede uygulama imkânı tanır. Roslyn, yalnızca bir derleyici değil, aynı zamanda .NET ekosisteminde yazılım geliştirme sürecini daha verimli hale getiren güçlü bir araç setidir.</p><ul><li><a href="https://learn.microsoft.com/tr-tr/dotnet/csharp/roslyn-sdk/">.NET Compiler Platform SDK&#39;sı (Roslyn API&#39;leri)</a></li><li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/compiler-api-model">.NET Compiler Platform SDK concepts and object model - C#</a></li><li><a href="https://github.com/dotnet/roslyn">GitHub - dotnet/roslyn: The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6d15b10c1477" width="1" height="1" alt=""><hr><p><a href="https://medium.com/intertechit/roslyn-net-i%C3%A7in-modern-derleyici-platformu-6d15b10c1477">Roslyn: .NET için Modern Derleyici Platformu</a> was originally published in <a href="https://medium.com/intertechit">Intertech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Dağıtılmış Sistemlerde Redis ve RedLock ile Kilitleme Mekanizmaları]]></title>
            <link>https://medium.com/intertechit/locking-mechanisms-with-redis-and-redlock-in-distributed-systems-e5c260412189?source=rss----d21876bad59---4</link>
            <guid isPermaLink="false">https://medium.com/p/e5c260412189</guid>
            <category><![CDATA[transactions]]></category>
            <category><![CDATA[distributed-locks]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <category><![CDATA[redlock]]></category>
            <category><![CDATA[redis]]></category>
            <dc:creator><![CDATA[Cihat Solak]]></dc:creator>
            <pubDate>Wed, 29 Jan 2025 07:22:23 GMT</pubDate>
            <atom:updated>2025-01-29T07:22:23.303Z</atom:updated>
            <content:encoded><![CDATA[<h4>Locking Mechanisms with Redis and RedLock in Distributed Systems</h4><p>Dağıtılmış sistemlerde, paylaşılan kaynaklara eşzamanlı erişim durumları kritik sorunlara yol açabilir. Veri tutarlılığının korunması, kaynak çakışmalarının önlenmesi ve sistem stabilizesinin sağlanması için etkili bir kilitleme 🔒 mekanizması gereklidir. <strong>Redis</strong> ve onun üzerinde inşa edilen <strong>RedLock algoritması</strong>, bu ihtiyacı karşılamak için güçlü bir çözüm sunar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qcirWaA8fxeI8eRnv2U9nw.jpeg" /><figcaption>Redis Redlock ensures consistency and safety in distributed locking mechanisms.</figcaption></figure><h4>RedLock Nedir?</h4><p>RedLock, Redis&#39;in temel kilitleme mekanizmasını kullanarak multi-node yapıdaki dağıtılmış sistemlerde tutarlı kilitleme sağlar. <a href="https://antirez.com/latest/0"><strong>Antirez</strong></a> tarafından tasarlanan bu algoritma, çoklu Redis sunucusunun senkronize çalışmasıyla kilitleme ve kilit serbest bırakma mekanizması sağlar. Redlock, Redis’â dayalı bir dağıtık kilitleme algoritmasıdır ve aşağıdakiler ve benzeri sorunları çözmeyi amaçlar:</p><p>🗄️ <strong>Veri Tutarlılığı:</strong> Aynı anda birden fazla işlemcinin aynı kaynağa erişmesini engeller.</p><p>👮🏻 <strong>Güvenlik :</strong> Redis sunucuları arasında doğru kilitlemeyi sağlar.</p><p>📈 <strong>Performans:</strong> Düşük gecikmeyle etkili kilitleme sağlar.</p><p>Redlock algoritması, birden fazla Redis sunucusu ile çalışacak şekilde tasarlanmış olup, dağıtılmış sistemlerde hataya tolerans ve güvenilirlik sağlar. Tek bir sunucu ile uygulanabilir ancak bu, algoritmanın dağıtılmış güvenlik amacını karşılamaz.</p><p><a href="https://github.com/samcook/RedLock.net">GitHub - samcook/RedLock.net: An implementation of the Redlock algorithm in C#</a></p><p>Redlock, dağıtık uygulamalarda işlemlerinizi kilitlemeden yürütmeye çalıştığınızda karşılaşılan veri tutarsızlığı, kaynak hataları ve performans sorunları gibi sorunları etkili bir şekilde çözerek, kaynakların doğru kullanılmasını ve sistemin tutarlılığını sağlar.</p><h4><strong>Örnek Kullanım Senaryoları</strong></h4><p>💬 <strong>Mesaj Kuyruğu İşlemleri: </strong>Bir mesaj kuyruğunda birden fazla tüketici aynı mesajın işlenmesine çalıştığında kilit mekanizması ile çakışma önlenir.</p><p>🚛 <strong>Stok Kontrolü: </strong>E-ticaret sitelerinde stok kontrolü yaparken, aynı ürünün birden fazla kişiye satılmaması için kilit sistemi kullanılabilir.</p><p>⏲️ <strong>Scheduled Tasks: </strong>Birden fazla sunucu üzerinde zamanlanmış görevlerin tekrar tekrar çalışmasını önlemek için dağıtılmış kilit kullanılabilir.</p><p><a href="https://www.nuget.org/packages/redlock.net/">RedLock.net 2.3.2</a></p><h4>RedLock Nasıl Kullanılır?</h4><p>RedLock kullanımı Redis kütüphaneleri 📚 aracılığıyla kolaylaştırılmıştır. Örneğin <a href="https://www.nuget.org/packages/stackexchange.redis"><strong>StackExchange.Redis</strong></a> ve <a href="https://www.nuget.org/packages/redlock.net/"><strong>RedLock.net</strong></a> kütüphaneleri bu işlemleri yönetmek için yaygın olarak kullanılır.</p><p>ASP.NET Core uygulamalarında RedLock genellikle <strong>Dependency Injection (DI)</strong> 💉 yapısı ile entegre edilir. Bu şekilde, merkezi bir Redis bağlantısı ve kilitleme mekanizması kullanılabilir.</p><p><strong>1.1 Redis Bağlantısı ve RedLock DI Kullanımı</strong></p><pre>// Redis bağlantı noktaları<br>var redisEndpoints = new[]<br>{<br>    new RedisConnectionConfiguration { EndPoint = new DnsEndPoint(&quot;localhost&quot;, 6379) },<br>    new RedisConnectionConfiguration { EndPoint = new DnsEndPoint(&quot;localhost&quot;, 6380) },<br>    new RedisConnectionConfiguration { EndPoint = new DnsEndPoint(&quot;localhost&quot;, 6381) }<br>};<br><br>// Redlock yapılandırması<br>var redlockFactory = RedLockFactory.Create(redisEndpoints);<br>builder.Services.AddSingleton&lt;IRedLockFactory&gt;(redlockFactory);</pre><p><strong>1.2 Kullanım</strong></p><pre>public class IntertechService<br>{<br>    private readonly IRedLockFactory _redLockFactory;<br><br>    public IntertechService(IRedLockFactory redLockFactory)<br>    {<br>        _redLockFactory = redLockFactory;<br>    }<br><br>    public async Task PerformTaskWithLockAsync()<br>    {<br>        string lockKey = &quot;intertech-service-lock&quot;;<br>        TimeSpan expiry = TimeSpan.FromSeconds(30);<br><br>        using var redLock = await _redLockFactory.CreateLockAsync(lockKey, expiry);<br>        if (redLock.IsAcquired)<br>        {<br>            // Kilit alındı, kritik işlem yapılabilir<br>            Console.WriteLine(&quot;Task running with lock.&quot;);<br>        }<br>        else<br>        {<br>            // Kilit otomatik olarak serbest bırakıldı (using bloğu)<br>            Console.WriteLine(&quot;Could not acquire lock.&quot;);<br>        }<br>    }<br>}</pre><h4>Wait ve Retry Parametreleri Ne İşe Yarar?</h4><p><strong>wait</strong> ve <strong>retry</strong> parametreleri, Redis üzerinde dağıtılmış kilit oluşturma işlemi sırasında kilidin alınmasını beklemek ve yeniden denemek için kullanılır.</p><p>⌚ <strong>WAİT</strong></p><ul><li><strong>Tanım:</strong> Kilidi almak için en fazla ne kadar süreyle bekleyeceğinizi belirler.</li><li><strong>Kullanım:</strong> Eğer kilit başka bir işlem tarafından tutuluyorsa, bu süre boyunca kilidin serbest bırakılmasını bekler. Belirtilen süre boyunca kilit alınamazsa, kilit alma işlemi başarısız olur.</li></ul><p>🔄 <strong>RETRY</strong></p><ul><li><strong>Tanım:</strong> Kilidi almak için yapılan denemeler arasında ne kadar süre bekleyeceğinizi belirler.</li><li><strong>Kullanım:</strong> Eğer bir kilit alınamazsa, belirtilen süre kadar bekledikten sonra yeniden deneme yapılır. Bu süreç, wait süresi dolana kadar devam eder.</li></ul><pre>string lockKey = &quot;the-thing-we-are-locking-on&quot;;<br>TimeSpan expiry = TimeSpan.FromSeconds(60);<br>TimeSpan wait = TimeSpan.FromSeconds(10);<br>TimeSpan retry = TimeSpan.FromSeconds(1);<br><br>var redLock = redLockFactory.CreateLock(lockKey, expiry);<br>if (redLock.IsAcquired)<br>{<br>    // Lock acquired<br>}<br>else<br>{<br>    // Lock not acquired<br>}<br><br>var redLock2 = redLockFactory.CreateLock(lockKey, expiry, wait, retry);<br>if (redLock2.IsAcquired)<br>{<br>    // Lock acquired<br>}<br>else<br>{<br>    // Lock not acquired<br>}</pre><blockquote>Bu satırda:</blockquote><blockquote><strong>wait = 10 saniye:</strong></blockquote><blockquote>Kilidi almak için en fazla 10 saniye boyunca bekleyecek.</blockquote><blockquote><strong>retry = 1 saniye:</strong></blockquote><blockquote>Eğer wait süresi içerisinde kilit alınamazsa, 1 saniye bekledikten sonra tekrar deneyecek.</blockquote><blockquote><strong>Sonuç:</strong></blockquote><blockquote>Eğer 10 saniye içinde kilit alınamazsa (lockKey’e ait farklı bir kilit varsa ve işlem kilidi serbest bırakmazsa), redLock2&#39;e ait kilit alma işlemi başarısız olarak işaretlenecek (<strong>redLock2.IsAcquired false</strong> olacak).</blockquote><blockquote>⚠️⚠️ Redlock instance’ına uzun süreli bir expiry süresi tanısanız bile, using bloğu kullanıldığında kilit, metodun sonunda otomatik olarak serbest bırakılacaktır. Buna dikkat etmeniz önemlidir.</blockquote><h4><strong>Bu Parametreler (Wait, Retry, Expiry, LockKey) Neden Kullanılır?</strong></h4><p>Bu mekanizma, kilit yarışını önler ve aynı kaynağı kullanmaya çalışan farklı işlemler arasında koordinasyon sağlar. Özellikle:</p><ul><li>Bir işlemin kilidi hemen alamaması durumunda belli bir süre beklemesi gerekebilir.</li><li>Aşırı yüklenmeyi önlemek için yeniden denemeler arasında bir bekleme süresi bırakılır.</li></ul><h3>👨🏻‍🏫 Basit Bir Örnek</h3><p>Bir senaryo düşünelim: E-ticaret platformunuzdaki bir stok güncelleme sistemi, bir ürünün stoğunu birden fazla işlemcinin aynı anda güncellemesini engellemelidir. Bu sorun kilitlenme olmadan çalışırsa, stok değerleri yanlış olabilir/güncellenebilir.</p><p>Redlock.net kullanarak bu sorunu çözelim:</p><pre>static void Main(string[] args)<br>    {<br>        // Redis Bağlantıları<br>        var redisConnections = new[]<br>        {<br>            ConnectionMultiplexer.Connect(&quot;localhost:6379&quot;),<br>            ConnectionMultiplexer.Connect(&quot;localhost:6380&quot;),<br>            ConnectionMultiplexer.Connect(&quot;localhost:6381&quot;)<br>        };<br><br>        using (var redlockFactory = RedLockFactory.Create(redisConnections))<br>        {<br>            var resource = &quot;lock:product:123&quot;; // Kilitlenecek kaynak<br>            var expiry = TimeSpan.FromSeconds(30); // Kilidin yaşam süreci<br><br>            using (var redLock = redlockFactory.CreateLock(resource, expiry))<br>            {<br>                if (redLock.IsAcquired)<br>                {<br>                    // Kritik işlem<br>                    Console.WriteLine(&quot;Stok güncelleniyor...&quot;);<br>                    // Stok güncelleme kodu buraya gelir<br>                }<br>                else<br>                {<br>                    Console.WriteLine(&quot;Kaynak kilitlendi, daha sonra tekrar deneyin.&quot;);<br>                }<br>            }<br>        }<br>    }</pre><h4>Sonuç</h4><p>Redis ve RedLock algoritması, dağıtılmış sistemlerde kaynak erişimi ve veri tutarlılığını sağlamak için etkili bir çözüm sunar. Kilit alma ve serbest bırakma mekanizmaları, performans ve tutarlılığı bir arada sunar. ASP.NET Core uygulamalarında Redis ve RedLock entegre edilerek, sistem stabilizesi ve veri güvenliği artırılabilir. Dağıtılmış sistemlerde kilitleme mekanizmalarına olan ihtiyacın artmasıyla, RedLock gibi çözümler kritik öneme sahiptir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/0*YzHt5V3phc743MFC.gif" /></figure><ul><li><a href="https://redis.io/glossary/redis-lock/">Redis Lock - Redis</a></li><li><a href="https://cheoalfredo.medium.com/distributed-locks-with-redis-net-2b1b50355deb">Distributed Locks with Redis + .NET</a></li><li><a href="https://medium.com/devopsturkiye/redlock-net-ile-distributed-lock-uygulayarak-concurrency-durumlar%C4%B1n%C4%B1-engelleyin-51eb000dba5e">RedLock.NET ile Distributed Lock uygulayarak Concurrency durumlarını engelleyin 🔒</a></li><li><a href="https://levelup.gitconnected.com/implementing-distributed-locks-with-redis-redlock-algorithm-for-dotnet-fbdc1bb567ee">Implementing Distributed Locks with Redis Redlock Algorithm for Dotnet</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e5c260412189" width="1" height="1" alt=""><hr><p><a href="https://medium.com/intertechit/locking-mechanisms-with-redis-and-redlock-in-distributed-systems-e5c260412189">Dağıtılmış Sistemlerde Redis ve RedLock ile Kilitleme Mekanizmaları</a> was originally published in <a href="https://medium.com/intertechit">Intertech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Sustainable Software Solutions with Clean Architecture]]></title>
            <link>https://medium.com/intertechit/sustainable-software-solutions-with-clean-architecture-bc1ac7987abc?source=rss----d21876bad59---4</link>
            <guid isPermaLink="false">https://medium.com/p/bc1ac7987abc</guid>
            <category><![CDATA[clean-architecture]]></category>
            <category><![CDATA[separation-of-concerns]]></category>
            <category><![CDATA[dependency-inversion]]></category>
            <category><![CDATA[persistence-ignorance]]></category>
            <category><![CDATA[inversion-of-control]]></category>
            <dc:creator><![CDATA[Cihat Solak]]></dc:creator>
            <pubDate>Mon, 06 Jan 2025 06:40:57 GMT</pubDate>
            <atom:updated>2025-01-06T06:40:57.912Z</atom:updated>
            <content:encoded><![CDATA[<h4>Clean Architecture Yaklaşımıyla Sürdürülebilir Yazılım Çözümleri</h4><blockquote><strong><em>If you’d like to read the content in Turkish, please scroll down.</em></strong><em> (İçeriği Türkçe olarak okumak isterseniz lütfen aşağı kaydırın.)</em></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZI1sXMdj1Ea5aKgn3o2Ilg.png" /><figcaption>Clean Architecture is a design paradigm that emphasizes the separation of concerns, ensuring that the core business logic remains independent of external frameworks, databases, or user interfaces.</figcaption></figure><h4>[ENG] <strong>Dependency Inversion/Inversion of Control Principle</strong></h4><p>The Dependency Inversion principle is one of the fundamental principles used to manage dependencies in software design. Typically, a class establishes a direct dependency on another class; for instance, the IntertechController class directly uses the IntertechService class. In such cases, the public components of IntertechService are directly accessible by IntertechController, resulting in a tightly coupled relationship between the two classes.</p><p>If a method within IntertechService is mistakenly defined as private, it could lead to errors in IntertechController. Similarly, if IntertechService depends on IntertechRepository, even minor changes in IntertechRepository can potentially affect the functionality of IntertechService.</p><p>The Dependency Inversion Principle proposes introducing an interface to eliminate this tight coupling. Through this approach, IntertechController does not directly depend on IntertechService but instead interacts with an interface of IntertechService. The class then works with any implementations of this interface. This method adheres to two key principles:</p><ol><li><strong>High-level modules should not depend on low-level modules. Both should depend on abstractions.</strong><br>The high-level module (e.g., IntertechController) should not directly know the low-level modules (e.g., IntertechService). Instead, an abstraction should mediate between them.</li><li><strong>Abstractions should not depend on details. Details should depend on abstractions.</strong><br>The methods defined in the interface should not reveal implementation details. For example, the GetBanks method should not expose specifics about where the data originates. These details should reside within the implementation class (e.g., IntertechService).</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/641/1*IgDZN7aZlvOWWcPvmvQ0GQ.jpeg" /><figcaption>The dependency principle states that high-level modules should not depend on low-level modules; both should depend on abstractions.</figcaption></figure><p>The Dependency Inversion Principle improves testability, reduces maintenance costs, and minimizes the impact of future changes on the system by breaking dependencies between modules.<strong> </strong>For instance, if IntertechController requires IntertechService and it is instantiated directly using the new keyword, any replacement of IntertechService with a different class would necessitate changes in IntertechController. However, if an interface is introduced, IntertechController would only rely on the interface of IntertechService. Consequently, when the implementation class of the interface is replaced, IntertechController remains unaffected.</p><blockquote><strong>Dependency Inversion and Inversion of Control (IoC) Are Distinct Concepts</strong><br>Dependency Inversion asserts that high-level modules should not directly depend on low-level modules; instead, such dependencies should be managed through an interface.</blockquote><blockquote>In contrast, Inversion of Control refers to the management of an object’s dependencies and lifecycle by an external control mechanism. IoC is often implemented using Dependency Injection, which enhances flexibility and testability.</blockquote><p><strong>Inversion of Control (IoC) Principle</strong><br>The Inversion of Control (IoC) principle prevents a class A from directly creating an instance of class B using the new keyword. Instead, class B is provided externally through constructor, method, or property injection. In this context, the dependency is referred to as the &quot;dependency object,&quot; while class A is called the &quot;dependent object.&quot; Although class A needs class B to function, it should not instantiate B directly.</p><p>These principles are commonly implemented using one of the most widely used design patterns: Dependency Injection (DI). DI frameworks facilitate the application of these principles. For instance, libraries like Autofac and Ninject act as frameworks by managing dependencies and enabling us to focus on writing our code.</p><p>The fundamental feature that differentiates a library from a framework is that, when integrated into a project, a framework uses your code rather than being directly used by your code.</p><blockquote><strong>Key Difference Between Framework and Library</strong><br>A framework is established when a library, once integrated into your project, takes control of your code. In other words, a library that governs the flow of your application code is considered a framework; otherwise, it remains a simple library.</blockquote><blockquote>Although it is partially correct to describe a framework as a collection of packages, the defining characteristic lies in how these packages interact with and utilize your code. In this context, Inversion of Control (IoC) and Dependency Injection (DI) frameworks play a crucial role. DI frameworks like Autofac and Ninject simplify dependency management.</blockquote><blockquote>Understanding these structures is essential for achieving efficiency and sustainability in software development.</blockquote><blockquote><strong>Library:</strong> You call it, and the control is in your hands.<br><strong>Framework:</strong> It calls you, and the control is in the framework’s hands.</blockquote><p><strong>Single Responsibility Principle (SRP)</strong><br>The Single Responsibility Principle states that a component (such as a class, module, or microservice) should have only one responsibility. The primary goal of this principle is to ensure that each component performs a single task and does it exceptionally well.</p><p>For example, it would violate SRP for a class to handle both email and fax sending functionalities. According to the formal definition, a component should have only one reason to change. This makes software easier to maintain and extend, as only the relevant responsibilities need to be reviewed when a modification is required.</p><p>Implementing SRP enhances code readability and simplifies testing, contributing to more sustainable and flexible software.</p><p>In conclusion, SRP is a critical principle for reducing complexity and improving manageability in the software development process.</p><p><strong>Persistence Ignorance</strong><br>Persistence Ignorance advocates that domain models, particularly entities and business logic, should have no knowledge of database processes. This principle ensures that entities do not carry details related to any ORM (Object-Relational Mapping) technology, such as Entity Framework Core. Consequently, entities remain unaware of which database technology is being used.<br>Persistence Ignorance ensures that the design of domain objects aligns with the ideal structure needed to solve business problems, ensuring that persistence processes do not compromise this design. Thus, entities and business logic operate independently of database details, focusing solely on business rules. This approach contributes to a more sustainable, testable, and modular application structure. Ultimately, the Persistence Ignorance principle helps make solutions related to business problems more understandable, allowing developers to concentrate more on the domain itself.</p><p><strong>Separation of Concern</strong><br>Separation of Concern (SoC) is a fundamental principle in software engineering and design that aims to divide complex systems into smaller, manageable parts. Its primary goal is to organize a system’s components so that each part focuses on a single concern or responsibility. Thus, instead of mixing multiple concerns, each component fulfills its designated function. This approach enhances the modularity, sustainability, and scalability of software systems.<br>In software development, SoC ensures clear separation between different areas such as business logic, data access, and user interface. For example, in the Model-View-Controller (MVC) design pattern, separating the model, view, and controller reflects this principle. Each layer handles specific responsibilities, making projects more readable, maintainable, and extendable.<br>Separation of Concerns is applicable not only in software development but also in various other domains. For instance, in a hospital setting, distinct roles such as doctors, nurses, and other staff contribute to more efficient organization. In software projects, this principle ensures components work independently, allowing each to focus on its own area of expertise. As a result, the overall system structure becomes more robust and comprehensible.</p><blockquote>Keep reading, it’s always exciting to discover! 🙂</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/335/0*kbjr4MJO0x43Pre-.gif" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/630/0*RYxWKXMAbJ5a5Wtk.png" /></figure><h3>Clean Architecture Yaklaşımıyla Sürdürülebilir Yazılım Çözümleri</h3><h4>Sustainable Software Solutions with Clean Architecture</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZI1sXMdj1Ea5aKgn3o2Ilg.png" /><figcaption>Clean Architecture, iş mantığının dış dünyadaki framework’lerden, veritabanlarından veya kullanıcı arayüzlerinden bağımsız kalmasını sağlayan sorumlulukların ayrımını vurgulayan bir tasarım paradigmasıdır.</figcaption></figure><h4>[TR] Dependency Inversion/Inversion Of Control Prensibi</h4><p>Dependency Inversion prensibi, bağımlılıkları yönetmek için kullanılan temel ilkelerden biridir. Genellikle, bir sınıfın başka bir sınıfa bağımlılığı doğrudan kurulur; örneğin, IntertechController sınıfı, IntertechService sınıfını doğrudan kullanır. Bu durumda, IntertechService&#39;deki public bileşenler, IntertechController tarafından doğrudan erişilebilir ve bu durum, iki sınıf arasında sıkı bir bağımlılık oluşturur. Eğer IntertechService içindeki bir metot yanlışlıkla private olarak tanımlanırsa, bu durum IntertechController&#39;da hatalara yol açabilir. Aynı şekilde, IntertechService&#39;in IntertechRepository&#39;ye bağımlı olması durumunda, IntertechRepository&#39;deki en küçük değişiklikler bile IntertechService&#39;i etkileyebilir.</p><p>Dependency Inversion prensibi, bu sıkı bağımlılığı ortadan kaldırmak için araya bir arayüz (interface) koymayı önerir. Bu sayede, IntertechController doğrudan IntertechService&#39;i değil, IntertechService&#39;in arayüzünü bilmekte ve bu arayüzü implement eden sınıflarla çalışmaktadır. Bu yaklaşımın iki önemli ilkesi vardır:</p><ol><li><strong>Yüksek Seviyeli Modüller, Düşük Seviyeli Modüllere Doğrudan Bağlı Olmamalıdır. (<em>High-level modules should not depend on low-level modules. Both should depend on abstractions.</em>):</strong> Yüksek seviyeli modül (örneğin, IntertechController), doğrudan düşük seviyeli modülleri (örneğin, IntertechService) bilmemeli ve arada bir soyutlama olmalıdır.</li><li><strong>Soyutlama Detaylar Üzerine Bağlı Olmamalıdır. (<em>Abstractions should not depend on details. Details should depend on abstractions.</em>):</strong> Arayüzde yer alan metodlar, uygulamanın iç detayları hakkında bilgi vermemelidir. Örneğin, GetBanks metodu, verinin nereden geldiği gibi detayları içermemelidir; bu detaylar, implementasyon sınıfında (örneğin, IntertechService) yer almalıdır.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/641/1*IgDZN7aZlvOWWcPvmvQ0GQ.jpeg" /><figcaption>Bağımlılık prensibi, üst düzey modüllerin alt düzey modüllere bağımlı olmaması gerektiğini, her ikisinin de soyutlamalara bağımlı olması gerektiğini ifade eder.</figcaption></figure><p>Dependency Inversion prensibi, modüller arasındaki bağımlılıkları kırarak, uygulamaların test edilebilirliğini artırır, bakım maliyetlerini düşürür ve gelecekte yapılacak değişikliklerin sistem üzerindeki etkisini minimumda tutar. Örneğin, eğer IntertechController içinde IntertechService&#39;e ihtiyaç duyuluyorsa ve doğrudan new ile örneklendirilmişse, IntertechService&#39;in yerine farklı bir sınıf kullanmak istendiğinde, IntertechController&#39;da değişiklik yapmak gerekecektir. Ancak arada bir arayüz varsa, IntertechController sadece IntertechService arayüzünü kullanmakta, dolayısıyla arayüzü implement eden sınıf değiştirildiğinde, IntertechController&#39;ın etkilenmemesi sağlanabilir.</p><blockquote>Dependency Inversion ve Inversion of Control (IoC) farklı kavramlardır. <strong>Dependency Inversion</strong>, yüksek seviyeli modüllerin düşük seviyeli modüllere doğrudan bağımlı olmaması gerektiğini savunur; bu bağımlılıkların bir arayüz aracılığıyla yönetilmesini sağlar. <strong>Inversion of Control</strong> ise, bir nesnenin bağımlılıklarının ve yaşam döngüsünün dış bir kontrol mekanizması tarafından yönetilmesi anlamına gelir. IoC, genellikle Dependency Injection ile uygulanarak, esneklik ve test edilebilirliği artırır.</blockquote><h4>Inversion of Control (IoC) Prensibi</h4><p>Bir A sınıfının B sınıfına ihtiyaç duyduğunda B sınıfını doğrudan new ile oluşturmasını engeller; bunun yerine B sınıfı, dışarıdan constructor, method veya property injection ile sağlanır. Bu bağlamda, B sınıfına olan bağımlılığa &quot;dependency object&quot; denirken, A sınıfı &quot;dependent object&quot; olarak adlandırılır. A sınıfı, işlevini yerine getirebilmek için B sınıfına ihtiyaç duyar, ancak B sınıfını doğrudan yaratmamalıdır. Bu prensipler, en çok kullanılan tasarım desenlerinden biri olan Dependency Injection (DI) ile uygulanır. DI framework’leri, bu prensipleri kolayca uygulamamıza yardımcı olur. Örneğin, Autofac ve Ninject gibi kütüphaneler, bağımlılıkları yönetirken kodlarımızı kullanmamızı sağlayarak bir framework işlevi görür. <strong>Bir kütüphaneyi framework olarak adlandıran temel unsur, projenize eklediğinizde, kütüphanenin sizin kodlarınızı kullanıyor olmasıdır.</strong></p><blockquote><strong>Framework ve Library Temel Fark</strong></blockquote><blockquote>Framework, bir kütüphanenin projenize entegre edildiğinde, sizin kodlarınızı kullanıyorsa oluşur. Yani, eklediğiniz kütüphane, uygulama kodunuz üzerinde kontrol sağlıyorsa bir framework olarak adlandırılır; aksi takdirde basit bir kütüphane (library) olur.</blockquote><blockquote>Paketlerin bir araya gelmesi kısmen doğru olsa da, asıl belirleyici nokta, eklediğiniz paketlerin kodlarınızı nasıl kullandığıdır. Inversion of Control (IoC) ve Dependency Injection (DI) framework’leri bu anlamda önemlidir. <strong>Autofac </strong>ve <strong>Ninject</strong> gibi DI framework’leri bağımlılık yönetimini kolaylaştırır. Bu yapıların anlaşılması, yazılım geliştirmede etkinlik ve sürdürülebilirlik için kritiktir.</blockquote><blockquote><strong>Kütüphane:</strong> Siz çağırırsınız, kontrol sizdedir.</blockquote><blockquote><strong>Framework:</strong> Sizi çağırır, kontrol framework’tedir.</blockquote><h4><strong>Single Responsibility Principle (SRP)</strong></h4><p>Yazılım tasarımında bir bileşenin (class, modül, mikroservis vb.) yalnızca tek bir sorumluluğa sahip olması gerektiğini belirtir. Bu ilkenin temel amacı, her bileşenin yalnızca bir işi olması ve o işi en iyi şekilde yerine getirmesidir. Örneğin, bir sınıfın hem e-posta hem de faks gönderme işlevini üstlenmesi, SRP’ye aykırıdır.</p><p>Resmi tanımına göre, bir bileşenin değişmesi için yalnızca bir nedeni olmalıdır. Bu, yazılımın bakımını ve genişletilmesini kolaylaştırır, çünkü bir bileşenin değiştirilmesi gerektiğinde, yalnızca ilgili sorumlulukların gözden geçirilmesi yeterlidir. SRP’nin uygulanması, kodun okunabilirliğini artırır ve test edilebilirliği kolaylaştırır; bu da yazılımın daha sürdürülebilir ve esnek olmasına katkıda bulunur.</p><p>Sonuç olarak, SRP, yazılım geliştirme sürecinde karmaşıklığı azaltmak ve yönetilebilirliği artırmak için kritik bir ilkedir.</p><h4>Persistence Ignorance</h4><p>Yazılım uygulamalarındaki domain modellerinin, özellikle entity’lerin ve iş mantığının veritabanı süreçleri ile ilgili hiçbir bilgiye sahip olmaması gerektiğini savunur. Bu prensip, entity’lerin herhangi bir ORM (Object-Relational Mapping) teknolojisiyle veya örneğin Entity Framework Core ile ilgili detaylar taşımamasını öngörür. Dolayısıyla, entity’ler dış dünyada hangi veritabanı teknolojisinin kullanıldığını bilmezler.</p><p>Persistence Ignorance, domain nesnelerinin tasarımının, iş problemini çözmek için gereken ideal yapı ile uyumlu olmasını sağlarken, kalıcılık süreçlerinin bu tasarımı kirletmemesini de temin eder. Böylece, entity’ler ve iş mantığı veritabanı detaylarıyla karışmadan, yalnızca iş kurallarını içerebilir. Bu yaklaşım, uygulamanın daha sürdürülebilir, test edilebilir ve modüler bir yapı kazanmasını sağlar. Sonuç olarak, Persistence Ignorance prensibi, iş problemleriyle ilgili çözümlerin daha anlaşılır olmasına ve geliştiricilerin iş alanına daha fazla odaklanmasına yardımcı olur.</p><h4><strong>Separation Of Concern</strong></h4><p>Yazılım mühendisliği ve tasarımında karmaşık sistemlerin daha küçük, yönetilebilir parçalara ayrılmasını amaçlayan temel bir ilkedir. Bu ilkenin temel amacı, bir sistemin bileşenlerini her bir parça tek bir konuya (concern) odaklanacak şekilde organize etmektir. Böylece, birden fazla konunun karıştırılması yerine her bileşen kendi işlevselliğini yerine getirir. Bu yaklaşım, yazılım sistemlerinin modülerliğini, sürdürülebilirliğini ve ölçeklenebilirliğini artırır.</p><p>Yazılım geliştirme bağlamında SoC, iş mantığı, veri erişimi ve kullanıcı arayüzü gibi farklı alanların net bir şekilde ayrılmasını sağlar. Örneğin, MVC (Model-View-Controller) tasarım kalıbında, model, görünüm ve kontrolcülerin ayrı ayrı ele alınması bu prensipten kaynaklanır. Her bir katman, belirli bir sorumluluk taşır ve bu sayede projeler daha okunaklı, bakımı kolay ve genişletilebilir hale gelir.</p><p>Separation of Concerns, sadece yazılım geliştirmede değil, birçok farklı alanda geçerli bir ilkedir. Örneğin, bir hastanede doktorlar, hemşireler ve diğer personelin ayrı ayrı roller üstlenmesi, karmaşık bir organizasyonu daha verimli hale getirir. Bu ilke, yazılım projelerinde bileşenlerin birbirinden bağımsız olarak çalışmasını sağlarken, aynı zamanda her bir bileşenin yalnızca kendi alanına odaklanmasına imkan tanır. Bu sayede, sistemin genel yapısı daha sağlam ve anlaşılır bir hale gelir.</p><blockquote>Okumaya devam edin, keşfetmek her zaman heyecan vericidir! 🙂</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/335/0*88sIAWNlwQUcPkSr.gif" /></figure><ul><li><a href="https://autofac.org/">Autofac: Home</a></li><li><a href="http://www.ninject.org/">Ninject</a></li><li><a href="https://learn.microsoft.com/en-us/archive/msdn-magazine/2009/june/the-unit-of-work-pattern-and-persistence-ignorance">The Unit Of Work Pattern And Persistence Ignorance</a></li><li><a href="https://www.geeksforgeeks.org/separation-of-concerns-soc/">Separation of Concerns (SoC) - GeeksforGeeks</a></li><li><a href="https://dev.to/brandongautama/building-software-with-clean-architecture-4h2g">Building Software with Clean Architecture</a></li><li><a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-9.0">Dependency injection in ASP.NET Core</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bc1ac7987abc" width="1" height="1" alt=""><hr><p><a href="https://medium.com/intertechit/sustainable-software-solutions-with-clean-architecture-bc1ac7987abc">Sustainable Software Solutions with Clean Architecture</a> was originally published in <a href="https://medium.com/intertechit">Intertech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Structural and Behavioural Differences of C#: Class, Record, Override and New]]></title>
            <link>https://medium.com/intertechit/structural-and-behavioural-differences-of-c-class-record-override-and-new-4bea83463e19?source=rss----d21876bad59---4</link>
            <guid isPermaLink="false">https://medium.com/p/4bea83463e19</guid>
            <category><![CDATA[csharp-programming]]></category>
            <category><![CDATA[record]]></category>
            <category><![CDATA[class]]></category>
            <category><![CDATA[object-oriented-program]]></category>
            <category><![CDATA[override]]></category>
            <dc:creator><![CDATA[Cihat Solak]]></dc:creator>
            <pubDate>Mon, 16 Dec 2024 07:03:23 GMT</pubDate>
            <atom:updated>2024-12-16T07:03:23.141Z</atom:updated>
            <content:encoded><![CDATA[<h4>C#’ın Yapısal ve Davranışsal Farklılıkları: Class, Record, Override ve New</h4><blockquote><strong>If you’d like to read the content in Turkish, please scroll down.</strong> (İçeriği Türkçe olarak okumak isterseniz lütfen aşağı kaydırın.)</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*M2NcDtrUwan_9m6qOWDg1Q.png" /><figcaption>In C#, class is used for complex operations, while record provides security in data transport.</figcaption></figure><h3>[ENG] Difference Between override and new Keywords in C#</h3><p>Object-oriented programming in C# is based on concepts such as inheritance and polymorphism. In inheritance, the keywords override and new are used to replace or hide methods from the base class in derived classes. Both keywords allow a method in a base class to be redefined in a derived class, but they differ in one important way.</p><h4>What is override?</h4><p>override allows a derived class to override a method in the base class. In this case, the overridden method in the derived class is executed, even if it is called by reference to the base class. For example:</p><pre>public class Shape<br>{<br>    public virtual void Draw() =&gt; Console.WriteLine(&quot;Drawing a shape&quot;);<br>}<br><br>public class Circle : Shape<br>{<br>    public override void Draw() =&gt; Console.WriteLine(&quot;Drawing a circle&quot;);<br>}<br><br>Shape shape = new Circle();<br>shape.Draw(); // Output: Drawing a circle</pre><p>In this code, the Draw method of the Circle class works even if the Shape reference is used. This indicates that polymorphism is provided when the override is used.</p><h4>What is new?</h4><p>The new keyword hides, but does not override, a method in the base class. In this case, the method of the base class is executed when the base class reference is used:</p><pre>public class Rectangle : Shape<br>{<br>    public new void Draw() =&gt; Console.WriteLine(&quot;Drawing a rectangle&quot;);<br>}<br><br>Shape shape = new Rectangle();<br>shape.Draw(); // Output: Drawing a shape</pre><p>Here, even though the Draw method is redefined in the Rectangle class, the Draw method in the base class is executed when called with a reference to Shape. <strong>This shows that no polymorphism is achieved with </strong><strong>new, only the base class method is hidden.</strong></p><h4>Differences in Brief</h4><ul><li><strong>override:</strong> Provides polymorphism; a derived class method is valid even if called with a base class reference.</li><li><strong>new:</strong> Hides the method; the base class method is executed when called with a base class reference.</li></ul><p>As a result, you should use override if you want the base class method to work with a derived class reference, and new if you just want to hide it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/0*TpXJkhWfONe0nOwm.gif" /><figcaption>In C#, override allows a method to be redefined and new allows it to be hidden.</figcaption></figure><h3>Differences between class and record in C#</h3><p>The record type, introduced with C# 9.0, is a type that focuses on managing data more easily and securely. Understanding the basic features that distinguish class and record structures is important to use the right type in the right situations.</p><h4>What is class?</h4><p>Class is the most widely used type in object oriented programming and acts as a reference type. Objects defined with class are stored in heap memory and accessed through their references in memory. Class is preferred especially in cases that require complex structures, behaviours and state management. Also, classes can contain methods, fields and various other members in addition to properties.</p><pre>public class Person<br>{<br>    public string Name { get; set; }<br>    public int Age { get; set; }<br>}</pre><h4>What is record?</h4><p>Record is a C# feature developed to make it easier to create immutable data types and acts as a reference type. records provide value equality by default, meaning that two record instances are considered equal if they have the same property values. This makes the record type particularly useful in data transport objects, data transfer and modelling situations.</p><pre>public record Person(string Name, int Age);</pre><p>In this example, we have defined properties directly in record and made them immutable. The properties of the Person instance cannot be changed; ‘with-expressions’ is used to create a new Person instance.</p><pre>var person = new Person(&quot;Alice&quot;, 30);<br>var updatedPerson = person with { Age = 31 };</pre><h4>Differences between class and record</h4><ul><li><strong>The main differences between record and class types are evident in their intended use and behaviour.</strong> record types are considered immutable by default; that is, their properties cannot be changed after creation. This property ensures that data can be safely transported and used without modification. <strong>In contrast, class types are mutable</strong>, meaning that their properties can be modified, making them more flexible.</li><li>There is also an important difference between the two types in terms of equality. <strong>record types use value equality</strong>; that is, if the property values of two record instances are the same, the two objects are considered equal. In contrast, <strong>class types use reference equality</strong>, meaning that two class objects are not considered equal unless they point to the same address in memory.</li><li>As for their intended use, <strong>record types are ideal for moving data and processing it without modification</strong>. Structures often called ‘Data Transfer Object (DTO)’ or ‘model’ are defined with this type. On the other hand, class types are suitable for representing objects with more complex behaviour and business logic. These differences become very important in determining the right use case.</li></ul><h4>When to use class and When to use record?</h4><ul><li><strong>Data Modelling and Transfer:</strong> It makes more sense to use record only if you are doing data transfer and modelling. For example, record is ideal for receiving data from the API.</li><li><strong>Business Logic and State Management:</strong> If you are working with mutable objects that contain behavioural properties and business logic, it is more appropriate to use class.</li></ul><blockquote>Keep reading, it’s always exciting to discover! 🙂</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HWi9lnca2gnohOElE8QeEw.png" /></figure><h3>[TR] C#’ta override ve new Anahtar Sözcükleri Arasındaki Fark</h3><p>C# dilinde nesne yönelimli programlama, kalıtım ve çok biçimlilik gibi kavramlar üzerine kuruludur. Kalıtımda temel sınıftaki metotları türetilmiş sınıflarda değiştirmek veya gizlemek için override ve new anahtar sözcükleri kullanılır. Her iki anahtar sözcük de temel sınıftaki bir metodu türetilmiş sınıfta yeniden tanımlamaya olanak sağlar, ancak birbirlerinden önemli bir farkla ayrılırlar.</p><h4>override Nedir?</h4><p>override, türetilmiş sınıfın temel sınıfta bulunan bir metodu geçersiz kılmasını sağlar. Bu durumda, temel sınıf referansı ile bile çağrılsa, türetilmiş sınıftaki override edilen metot çalıştırılır. Örneğin:</p><pre>public class Shape<br>{<br>    public virtual void Draw() =&gt; Console.WriteLine(&quot;Drawing a shape&quot;);<br>}<br><br>public class Circle : Shape<br>{<br>    public override void Draw() =&gt; Console.WriteLine(&quot;Drawing a circle&quot;);<br>}<br><br>Shape shape = new Circle();<br>shape.Draw(); // Output: Drawing a circle</pre><p>Bu kodda, Shape referansı kullanılsa bile Circle sınıfının Draw metodu çalışır. Bu, override kullanıldığında çok biçimliliğin sağlandığını gösterir.</p><h4>new Nedir?</h4><p>new anahtar sözcüğü, temel sınıftaki bir metodu gizler, ancak geçersiz kılmaz. Bu durumda, temel sınıf referansı kullanıldığında temel sınıfın metodu çalıştırılır:</p><pre>public class Rectangle : Shape<br>{<br>    public new void Draw() =&gt; Console.WriteLine(&quot;Drawing a rectangle&quot;);<br>}<br><br>Shape shape = new Rectangle();<br>shape.Draw(); // Output: Drawing a shape</pre><p>Burada Draw metodu Rectangle sınıfında yeniden tanımlanmış olsa da, Shape referansı ile çağrıldığında temel sınıftaki Draw metodu çalışır. Bu, new ile <strong>çok biçimliliğin sağlanmadığını, sadece temel sınıf metodunun gizlendiğini gösterir.</strong></p><h4>Kısaca Farklar</h4><ul><li><strong>override:</strong> Çok biçimlilik sağlar; türetilmiş sınıf metodu temel sınıf referansı ile çağrılsa bile geçerli olur.</li><li><strong>new:</strong> Metodu gizler; temel sınıf referansı ile çağrıldığında temel sınıfın metodu çalışır.</li></ul><p>Sonuç olarak, temel sınıftaki metodun türetilmiş sınıf referansı ile çalışmasını istiyorsanız override, sadece gizlemek istiyorsanız new kullanmalısınız.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/0*TpXJkhWfONe0nOwm.gif" /><figcaption>C#’ta override, bir metodun yeniden tanımlanmasını; new ise gizlenmesini sağlar.</figcaption></figure><h3>C#’ta class ve record Arasındaki Farklar</h3><p>C# 9.0 ile birlikte tanıtılan record türleri, veriyi daha kolay ve güvenli bir şekilde yönetmeye odaklanan bir türdür. class ve record yapılarını birbirinden ayıran temel özellikleri anlamak, doğru durumlarda doğru türü kullanmak için önemlidir.</p><h4>class Nedir?</h4><p>class, nesne yönelimli programlamada en yaygın kullanılan türdür ve referans tipi olarak davranır. class ile tanımlanan nesneler heap hafızada saklanır ve bellekte referansları üzerinden erişilir. Özellikle karmaşık yapılar, davranışlar ve durum yönetimi gerektiren durumlarda class tercih edilir. Ayrıca, class’lar içinde özelliklerin yanında yöntemler (methods), alanlar (fields) ve çeşitli diğer üyeler barındırabilir.</p><pre>public class Person<br>{<br>    public string Name { get; set; }<br>    public int Age { get; set; }<br>}</pre><h4>record Nedir?</h4><p>record, immutable (değişmez) veri türleri oluşturmayı kolaylaştırmak için geliştirilen bir C# özelliğidir ve referans tipi olarak davranır. record’lar varsayılan olarak value equality sağlar, yani iki record örneği aynı özellik değerlerine sahipse eşit kabul edilir. Bu, record türünü özellikle veri taşıma nesneleri, veri transferi ve modelleme durumlarında kullanışlı hale getirir.</p><pre>public record Person(string Name, int Age);</pre><p>Bu örnekte, record içinde özellikleri doğrudan tanımladık ve immutable olmaları sağlandı. Person örneğinin özellikleri değiştirilemez; yeni bir Person örneği oluşturmak için &quot;with-expressions&quot; kullanılır.</p><pre>var person = new Person(&quot;Alice&quot;, 30);<br>var updatedPerson = person with { Age = 31 };</pre><h4>Class ve Record Arasındaki Farklar</h4><ol><li><strong>record ve </strong><strong>class türleri arasındaki temel farklar, kullanım amaçları ve davranışları açısından belirgindir.</strong> record türleri varsayılan olarak <strong>immutable</strong> kabul edilir; yani oluşturulduktan sonra özellikleri değiştirilemez. Bu özellik, verilerin güvenli bir şekilde taşınmasını ve değiştirilmeden kullanılmasını sağlar. Buna karşılık, <strong>class türleri mutable’dır</strong>, yani özellikleri üzerinde değişiklik yapılabilir ve bu da onları daha esnek kılar.</li><li>Eşitlik açısından da iki tür arasında önemli bir farklılık bulunur. <strong>record türleri value equality</strong> kullanır; yani iki record örneğinin özellik değerleri aynıysa, bu iki nesne eşit kabul edilir. Buna karşın, <strong>class türleri referans eşitliği</strong> esas alır; yani bellekte aynı adresi işaret etmedikçe iki class nesnesi eşit sayılmaz.</li><li>Kullanım amaçlarına gelince, <strong>record türleri veri taşımak ve değişiklik yapılmadan işlemek için idealdir</strong>. Genellikle &quot;Data Transfer Object (DTO)&quot; ya da &quot;model&quot; olarak adlandırılan yapılar bu türle tanımlanır. Öte yandan, <strong>class türleri daha karmaşık davranışları ve iş mantığını içeren nesneleri temsil etmek için uygundur</strong>. Bu farklar, doğru kullanım senaryosunu belirlemek açısından oldukça önemli hale gelir.</li></ol><h4>Ne Zaman class ve Ne Zaman record Kullanmalı?</h4><ul><li><strong>Veri Modelleme ve Transferi:</strong> Sadece veri taşıma ve modelleme yapıyorsanız record kullanımı daha mantıklıdır. Örneğin, API’den gelen veriyi almak için record idealdir.</li><li><strong>İş Mantığı ve Durum Yönetimi:</strong> Davranışsal özellikler ve iş mantığı içeren, değişebilir (mutable) nesnelerle çalışıyorsanız class kullanmak daha uygundur.</li></ul><blockquote>Okumaya devam edin, keşfetmek her zaman heyecan vericidir! 🙂</blockquote><ul><li><a href="https://learn.microsoft.com/en-us/answers/questions/1003951/c-difference-between-record-and-class">C# Difference between Record and class - Microsoft Q&amp;A</a></li><li><a href="https://medium.com/@kamaleshs48/difference-between-class-and-record-type-in-c-c387573dc49b">Difference between class and record type in C#</a></li><li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords">Knowing When to Use Override and New Keywords - C#</a></li><li><a href="https://www.c-sharpcorner.com/UploadFile/2072a9/virtual-vs-override-vs-new-keywords-in-csharp/">Virtual vs Override vs New Keywords in C#</a></li><li><a href="https://alinabo.com/csharp-record-vs-class">C# Record vs Class: Key Differences and Best Use Cases</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4bea83463e19" width="1" height="1" alt=""><hr><p><a href="https://medium.com/intertechit/structural-and-behavioural-differences-of-c-class-record-override-and-new-4bea83463e19">Structural and Behavioural Differences of C#: Class, Record, Override and New</a> was originally published in <a href="https://medium.com/intertechit">Intertech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>