23 Şubat 2026 Pazartesi

Source code comments ve Decision Context

Giriş
Bu yazı Kod Gözden Geçirmesi - Code Review sürecinden yola çıkarak başladı. Kod Gözden Geçirmesi  sürecinde şöyle bir madde vardı.

1. Source code comments are sufficient :
Yazan cümleler genelde şöyle. İşte burada görecelilik ön plana çıkıyor.
  • If there is a comment, does it explain why the code does what it does?
  • Is each line of the code - in its context - either self-explanatory enough that it does not need a comment, or if not, is it accompanied by a comment which closes that gap?
  • Can the code be changed so it does not need a comment any more?
Emniyet kritik bazı projelerde her satır için comment olması isteniyor. O zaman iş sanki biraz daha kolay. Sadece her satıra bakmak yeterli. Kod şöyle görünüyor.
/* Display an error message */
function display_error_message( $error_message )
{
  /* Display the error message */
  echo $error_message;

  /* Exit the application */
  exit();
}

/* -------------------------------------------------------------------- */

/* Check if the configuration file does not exist, then display an error */
/* message */
if ( !file_exists( 'C:/xampp/htdocs/essentials/configuration.ini' ) ) {
  /* Display an error message */
  display_error_message( 'Error: ...');
}
Yapılması gerekenlere bazı örnek
- Source code conforms to coding standard and is checked by automated tool
- Source code is checked manually by reviewer if automation is not possible
- Source code is checked for memory leaks by a dedicated tool
- Source code is compatible and traceable to SRS

2. The Pattern I Notice in Every High-Quality Codebase
Yüksek kalite kodlarda bir karar yani "neden" açıklaması vardır. Açıklaması şöyle
I've started noticing four types of decision context that great codebases maintain:
...
Without this context, all code looks equally arbitrary.
1. Business context — Why this business rule exists
Örnek şöyle
// Stripe charges 2.9% + $0.30 per transaction
// We pass this through to users on transactions <$10
// For larger transactions, we absorb it (reduces churn by 8%)
const FEE_THRESHOLD = 1000; // in cents
2. Historical context — Why we chose this approach
Örnek şöyle
// We tried async/await here but hit deadlocks under load
// See incident post-mortem: docs/incidents/2024-01-15-deadlock.md
// Synchronous approach is slower but reliable
fn process_batch_sync(items: Vec<Item>) -> Result<()> {
3. Constraint context — What limits our options
Örnek şöyle
// API rate limited to 100 req/min per docs/api-limits.md
// We batch requests to stay under limit with 20% safety margin
const maxRequestsPerMinute = 80
 4. Future context — What we plan to change
Örnek şöyle
// TODO: Move to event-driven architecture
// Blocked on: Kafka cluster provisioning (INFRA-445)
// Timeline: Q2 2024
// This polling approach is temporary
pollForUpdates();




18 Şubat 2026 Çarşamba

Data Models

Giriş
Yazıyı (10 Data Models Every Data Engineer Must Know (Before They Break Production)) ilk olarak burada gördüm.

OLTP
PostgreSQL, MySQL, Oracle gibi veri tabanları. Bunları tasarlarken normalization yapılır. Bunlar için 
2000'li yıllarda ER Diagrams ve 3NF (Third Normal Form) kullanılıyordu. Halen de kullanılıyor

OLAP
Şu sorulara cevap vermek zor olduğu için OLAP veri tabanlarına ihtiyaç var.
-- Revenue by product category for Q3 2024
-- Requires joining 5 tables just to get to the numbers
SELECT
    p.category_id,
    SUM(oi.quantity * oi.unit_price) AS total_revenue
FROM order_items oi
JOIN orders o      ON oi.order_id    = o.order_id
JOIN customers c   ON o.customer_id  = c.customer_id
JOIN products p    ON oi.product_id  = p.product_id
JOIN payments pay  ON o.payment_id   = pay.payment_id
WHERE o.order_date BETWEEN '2024-07-01' AND '2024-09-30'
  AND pay.status = 'completed'
GROUP BY p.category_id;
OLAP veri tabanı için iki tane yöntem var
1. Road A: Inmon — Build the Enterprise Core First
Veri pek çok farklı sistemden geliyor ve aynı şey için farklı ID, ve isimler verilmiş. Bill Inmon şunu teklif ediyor.
His suggestion is to build a single, normalized enterprise data warehouse that integrates all source systems first — still in 3NF, same structural logic as OLTP — and treat that as the only one authoritative version of Mr. Data for the whole company.

Next, we create data marts using that clean core as the foundation. These are smaller analytical views designed for specific teams. For example, the e-commerce team gets a mart shaped for their specific needs, and finance gets another. We make sure Mr. Data remains one consistent record, so he stays the same in every report the company runs.
2. Road B: Kimball — Flatten It, Ship It, Iterate
Açıklaması şöyle
Ralph Kimball looked at the same problem and started from the other end: what do analysts actually ask?

He noticed that every analytical question has the same shape: How much of X, by Y, over time Z?

- Revenue by product category by quarter.
- Returns by region by month.
- Orders by customer segment by year.

The “how much” is always a number being aggregated. The ‘by’ clauses are your filters and groupings.

Therefore, Kimball thought that we could build the schema around that shape, so that analysts don’t need to reconstruct it through multiple joins.
Açıklaması şöyle
- The “how much” becomes a fact table — one row per order line item, holding Mr. Data’s quantities, prices, and totals.
- The “by” dimensions — product, customer, date — become dimension tables surrounding it.
The technique that makes this possible is denormalization — the opposite of the OLTP and Inmon approach.
Yani ortaya fact tablosunu alıyoruz ve dimension tabloları ile JOIN yapıyoruz
Örnek
Şöyle yaparız. Buna start schema deniyor
-- Revenue by product category for 2024
-- Two joins. That's it.
SELECT
    p.category,
    d.quarter,
    SUM(f.total_revenue) AS revenue
FROM fact_orders f
JOIN dim_product  p ON f.product_key = p.product_key
JOIN dim_date     d ON f.date_key    = d.date_key
WHERE d.year = 2024
GROUP BY p.category, d.quarter
ORDER BY revenue DESC;
Açıklaması şöyle
When we put the fact table in the center and the dimensions around it, we get a star schema. Mr. Data’s order still exists, but now it’s been flattened and reshaped so an analyst can reach it in two joins instead of five.
10. Star Schema: The Legacy Workhorse (That Fails at Scale)
2010'lu yıllardan itibaren Star Schemas and Dimensions çıktı. Burada amaç correctness değil, amaç analitik işler için kolay sorgulama. Açıklaması şöyle.
Star schemas are intuitive and analyst-friendly, but at scale they become a performance bottleneck, especially with massive fact tables, high-cardinality dimensions, and near-real-time workloads.
Fact Table:
Event'leri içerir

Dimension Table
Eventiçindeki descriptions bilgisini içerir.

Örnek
Normal dimension

Suppose you have customers.

Fact table

CustomerKey Amount
1                 100
2                 50

Customer dimension

CustomerKey Name City
1                 Alice Ankara
2                 Bob         İzmir
Degenerate dimension eğer event içindeki bir bilgi için dimension yani description bulamıyorsak, fact tablosunda olduğu gibi saklanması anlamına geliyor. OrderNumber, InvoiceNumber, ReceiptNumber,
TransactionId gibi bilgiler dimension tablosuna girmez çünkü detaylandıracak bir şey yok. Bu yüzden Fact tablosunda kalmaya devam eder

9. Snowflake Schema: Over-Engineered & Slow
Açıklaması şöyle.
Snowflake schemas optimize storage, not query performance. In modern analytics (cloud OLAP, dashboards, ad-hoc queries), compute is the bottleneck, not disk. Excessive normalization explodes join depth and kills latency.
8. Data Vault: The Enterprise Monster (When You Need Auditability)
2020'li yıllarda çıktı. Açıklaması şöyle.
Data Vault excels at auditability, lineage, and full historization, critical for regulated industries (banking, healthcare). But its multi-layer architecture makes it fundamentally unsuited for low-latency analytics.
Burada veri kaynağının çok sık değişmesi ve audit, tarihçe istekleri önemli

7. Wide-Column Stores (Cassandra, Bigtable) for Time-Series Chaos
Açıklaması şöyle. 
Wide-column databases dominate high-velocity ingest (IoT, metrics, logs) where writes never stop. But they sacrifice query flexibility, no joins, limited filtering, and rigid access patterns. You win on writes, lose on exploration.
6. Graph Models (Neo4j, TigerGraph) for Hidden Relationships
Açıklaması şöyle.
When insight lives in relationships (fraud rings, social influence, network hops), relational joins collapse under recursive depth. Graph databases treat relationships as first-class citizens, making multi-hop traversals fast and natural.
5. Streaming Event Sourcing (Kafka + CDC)
Açıklaması şöyle.
Batch ETL is fundamentally incompatible with real-time systems. CDC turns database mutations into immutable events, enabling near-zero-latency pipelines, replayable state, and system-wide consistency across microservices.
4. Columnar Storage (Parquet, Delta Lake) for Cheap, Fast Analytics
Parquet bir örnek
Açıklaması şöyle.
Row-based databases are optimized for point lookups, not scans. Analytics workloads read a few columns across billions of rows, exactly what columnar storage is built for. The result: orders-of-magnitude faster queries at a fraction of the cost.
Örnek
Şöyle yaparız
CREATE TABLE sales_parquet (
    order_id BIGINT,
    region   STRING,
    amount   DECIMAL(10,2),
    order_ts TIMESTAMP
)
USING PARQUET
PARTITIONED BY (region, order_date);

SELECT
    region,
    SUM(amount) AS total_sales
FROM sales_parquet
WHERE order_date = '2025-12-25'
  AND region = 'US'
GROUP BY region;
Açıklaması şöyle. 
Why this is fast
- Only amount and region columns are read
- Only the order_date=2025-12-25 and US partitions are scanned
- All other files are skipped entirely
3. Multi-Model Hybrids (When SQL + NoSQL Collide)
2026 ve sonrasında artık şu kavramlar önemli
Iceberg, dbt, Data Contracts, and LLM-Aware Schemas

Ayrıca çoklu modeller de önemli. Açıklaması şöyle. Burada veri tabanının JSONB sütunları desteklemesi önemli
Real-world data is rarely one shape. Modern apps mix relational facts, semi-structured JSON, and relationships. Multi-model databases let you query everything in one place, without forcing awkward ETL or duplicating data.

1. The Unified Serving Layer (The Future of Production Data)
One dataset. Many engines. Zero rewrites. Açıklaması şöyle
Modern data stacks fracture data across OLTP, OLAP, search, and streaming systems, creating sync lag and duplicated logic. A Unified Serving Layer uses one logical data layer (Iceberg/Hudi/Delta) with multiple access modes: SQL analytics, near-real-time reads, ML, and even graph/search workloads.



7 Temmuz 2025 Pazartesi

Hot Row Contention

Giriş
Açıklaması şöyle. Yani aynı satıra çok fazla istek gelmesi ve bu isteklerin mecburen beklemesi
At its core, hot row contention arises from how databases manage concurrent data modifications. In a typical relational database (like MySQL, PostgreSQL, or SQL Server), when a transaction needs to update a row, it acquires an exclusive lock on that row. This lock prevents other transactions from modifying the same row simultaneously, ensuring data integrity and consistency (the “I” and “C” in ACID).

When many concurrent transactions converge on the exact same row — our “hot row”— they are forced to queue up, waiting for the current lock holder to finish.
Açıklaması şöyle
The problem isn't how many keys each shard has. It's how much traffic each key attracts. 
Bazı Çözümler
1. Append-Only Ledger Model: Prioritizing Writes
Örnek ver
2. Internal Sharding of Hot Accounts: Divide and Conquer
Bu işi hem okuma ağırlıklı (read heavy) hem de yazma (write heavy ) olarak düşünebiliriz

Okuma için bir örnek burada
# Single copy: one node handles all reads for taylorswift
cache.get("user:taylorswift")  # Always hits shard_1

# Replicated: spread reads across N copies
def get_hot_key(key):
    replica_id = random.randint(0, NUM_REPLICAS - 1)
    replica_key = f"{key}:replica:{replica_id}"

    result = cache.get(replica_key)
    if result:
        return result

    # Fallback to primary
    result = cache.get(key)
    return result

def set_hot_key(key, value):
    # Write to primary
    cache.set(key, value)
    # Fan out to all replicas
    for i in range(NUM_REPLICAS):
        cache.set(f"{key}:replica:{i}", value)
Yazma için bir örnek burada
#  Single counter: all writes hit one key
redis.incr("post:viral:likes")  # 100K writes/sec on ONE node

# Sharded counter: spread writes across N sub-keys
NUM_COUNTER_SHARDS = 100

def increment_like(post_id):
    shard = random.randint(0, NUM_COUNTER_SHARDS - 1)
    redis.incr(f"post:{post_id}:likes:shard:{shard}")

def get_like_count(post_id):
    total = 0
    pipe = redis.pipeline()
    for shard in range(NUM_COUNTER_SHARDS):
        pipe.get(f"post:{post_id}:likes:shard:{shard}")
    results = pipe.execute()
    return sum(int(r or 0) for r in results)
3. (In-Memory) Buffers and Batching: Absorbing the Spikes
Açıklaması şöyle. Yani aynı satıra çok fazla istek gelmesi ve bu isteklerin mecburen beklemesi
This technique involves intercepting incoming transactions and temporarily holding them in a fast in-memory buffer or a dedicated caching system (like Redis) instead of writing each one directly to the main database. These buffered transactions are then flushed to the persistent database in larger, consolidated batches.
4. Event-Driven Architecture (CQRS): Ultimate Separation of Concerns
Açıklaması şöyle. Yani aynı satıra çok fazla istek gelmesi ve bu isteklerin mecburen beklemesi
This architectural pattern addresses contention by making the write path highly optimized for appending events, which is inherently less contentious. Read paths query dedicated data models that don’t compete with write operations. This separation allows write and read workloads to be scaled independently to a very high degree.
5. Before overhauling your architecture — Optimistic Locking (OCC)

12 Haziran 2025 Perşembe

TCP Handshake - Maximum Segment Size (MSS)

Maximum Segment Size (MSS)
MSS iki taraf arasındaki bağlantıda, bir IP paketine sığdırılabilecek en büyük TCP paketi anlamına gelir. MSS sadece TCP'de vardır. UDP'de yoktur. Açıklaması şöyle
.. and then there's TCP MSS, which helps in case of TCP, but of course not with UDP nor ICMP.

Using the MSS field in the TCP header (only in the SYN and SYN-ACK packets of the initial 3-way handshake), hosts can signal to their peers how large a TCP payload is acceptable to receive.

TCP MSS negotiation can be a blessing, but also a nuisance, as it helps to hide MTU problems until something with large UDP packets comes along and fails at the "all hosts on the common L2 segment need to use the same MTU" criterium
Her iki taraf ta MSS değerini Bildirir ve Küçük Olanı Kullanılır
Açıklaması şöyle 
both hosts announce the MSS independently in the SYN and the SYN/ACK packets and the smaller of the two is chosen for all segments exchanged during the entire duration of the connection.
Otomatik MSS Hesaplama
Dynamic Path MTU Discovery özelliği etkinse, IP seviyesinde en büyük MTU değeri biliniyor demektir. MSS bu MTU değeri kullanılarak hesaplanır.

Örnek
Örneğin Maximum Transmission Unit 1500 byte kabul edilirse, 20 byte IP ve 20 byte TCP zarflaması çıkarılırsa MSS 1460 byte olur.
MSS = 1500 - 20 - 20
MSS = 1460 bytes of TCP data

Kendi arayüzlerimizin MTU değerlerini öğrenmek için şöyle yaparız

MSS Değerini Kodla Atamak
Şöyle yaparız
int mss = 1200; // Desired MSS value
// Set MSS for the socket
if (setsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss)) < 0) {
  perror("Setting MSS failed");
  close(sockfd);
  return 1;
}
Kodla Atanırsa MSS Her Zaman MTU'da Küçük Olmalı
Açıklaması şöyle. MSS değeri MTU'dan küçük olmalı. Eğer MTU'dan büyük TCP paketleri kullanılırsak çok fazla fragmentation olur ve verim düşer.
TCP itself uses the MSS to determine the segment size, which should fit the MTU, but I have seen people do stupid things like set the MSS to much larger than the MTU (thinking it will increase the speed, but the effect is the opposite). That forces IP to create fragments prior to sending.
MSS Olarak 1460
Açıklaması şöyle. 1460 eskidendi artık bu değer 1448 oldu
The value 1460 was only common in the late 20th century because Ethernet was common, Ethernet frames have a standard 1500 byte payload capacity (which becomes the IP MTU), and IP and TCP headers were both 20 bytes long in those days. However, around the turn of the 21st century, networks had gotten fast enough that TCP needed to add the 12-byte TCP Timestamp option to protect against wrapped TCP sequence numbers, so typical TCP headers are 32 bytes long now, resulting in a typical 1448 byte TCP MSS on a standard 1500 byte MTU Ethernet network.
Diğer MSS Değerleri
Açıklaması şöyle
On networks with higher path MTUs than 1500 (example: data center networks that use nonstandard 6k or 9k jumbo Ethernet frames), the MSS will be larger. On networks with lower path MTUs than 1500 (example: PPPoE, common on DSL, has 8 additional bytes of overhead for an MTU of 1492), the MSS will be lower.
En Büyük MSS Değeri
Açıklaması şöyle. IP zarfındaki alanını alabileceği en büyük değer 65,535.
The Total Length field in the IP header is 16 bit and thus an IP packet (and therefore TCP packet) can not be larger than 65535 bytes. The TCP payload is actually even smaller since you have to subtract the TCP header from maximum packet size of the IP packet. 
IP zarfındaki bu değer kullanılan TCP zarfına göre biraz daha küçülüp 
65,495 - 40 byte daha küçük
veya
65,483 - 52 byte daha küçük olabiliyor.  Açıklaması şöyle
IPv4's max datagram size (the largest MTU it can fill up) is 2^16 bytes (i.e. 64KiB or 65535 bytes). So the max TCP MSS by today's standards is 65,483 bytes with TCP timestamps on, or 65,495 with them disabled.

3 Haziran 2025 Salı

ISO 9001

Giriş
Bir çok firma ISO 9001:2000 belgesi alıyor. 

ISO 9001 sadece yapılan işi tarif eden bir süreç olmasını gerektiriyor. İş için kullanılan araçlarla ilgilenmiyor. CMMI ile kıyaslanınca daha yüzeysel.

Bir başka açıklama şöyle
While ISO 9001 and the CMMI for Development provide road maps of good quality practice, the IEEE software and systems engineering standards provide more detailed "how-to" information and guidance.

18 Nisan 2025 Cuma

Modular Multiplicative Inverse

Giriş
Açıklaması şöyle
1. M seçimi : Pick a modulus M, which should be one more than the maximum value the field can hold.
In this case, since the max is 255, we choose M = 256.
2. P seçimi : Pick a number P that’s coprime with M (i.e., they share no common factors except 1).
Let’s go with P = 9.
3. Q seçimi : Now, a number Q such that (P × Q) mod M = 1. Q = 57
Örnek
encoded_value = (original_value * P) % M
original_value = (encoded_value * Q) % M

195 değeri için
219= (195 * 9) % 256
195 = (219 * 57) % 256

7 Ocak 2025 Salı

aws ce - Cost Expolorer Seçeneği

Örnek
Şöyle yaparız
aws ce get-reservation-utilization
Açıklaması şöyle
In AWS, use Cost Explorer to view your reserved instance utilization and identify opportunities for optimization: