Low-level design: Bir otopark (parking lot) sistemini nesne yönelimli olarak tasarlayın.

Cevap

LLD sorularında beklenen; gereksinimleri netleştirmek, ana sınıfları ve ilişkilerini çıkarmak, uygun desenleri seçmek ve kritik metotları kodlamaktır. Mükemmel bir UML değil, mantıklı sorumluluk dağılımı aranır.

1. Gereksinimleri netleştirin

  • Birden fazla kat, her katta farklı boyutta yerler (motosiklet, kompakt, büyük).
  • Araç girişte bilet alır, çıkışta süreye göre ücret öder.
  • Uygun yer yoksa giriş reddedilir; anlık boş yer sayısı gösterilir.
  • Kapsam dışı (sorun): rezervasyon, çoklu giriş kapısında eşzamanlılık detayları.

2. Ana sınıflar

SınıfSorumluluk
ParkingLotKatları yönetir, giriş/çıkış akışını koordine eder
LevelKendi yerlerini tutar, uygun yer bulur
ParkingSpotBoyut, dolu/boş durumu, park etmiş araç
VehiclePlaka ve boyut (Motorcycle, Car, Truck)
TicketAraç, yer, giriş zamanı
PricingStrategyÜcret hesaplama (Strategy deseni)

3. Kod iskeleti

from enum import Enum
from datetime import datetime
from abc import ABC, abstractmethod
import math, uuid

class Size(Enum):
    SMALL = 1; MEDIUM = 2; LARGE = 3

class Vehicle:
    def __init__(self, plate: str, size: Size):
        self.plate, self.size = plate, size

class ParkingSpot:
    def __init__(self, spot_id: str, size: Size):
        self.id, self.size, self.vehicle = spot_id, size, None
    def can_fit(self, v: Vehicle) -> bool:
        return self.vehicle is None and v.size.value <= self.size.value

class Level:
    def __init__(self, spots):
        self.spots = spots
    def find_spot(self, v):
        return next((s for s in self.spots if s.can_fit(v)), None)

class Ticket:
    def __init__(self, vehicle, spot):
        self.id = str(uuid.uuid4())
        self.vehicle, self.spot, self.entry = vehicle, spot, datetime.now()

class PricingStrategy(ABC):
    @abstractmethod
    def price(self, ticket: Ticket, exit_time: datetime) -> float: ...

class HourlyPricing(PricingStrategy):
    RATES = {Size.SMALL: 20, Size.MEDIUM: 40, Size.LARGE: 80}
    def price(self, ticket, exit_time):
        hours = math.ceil((exit_time - ticket.entry).total_seconds() / 3600) or 1
        return hours * self.RATES[ticket.vehicle.size]

class ParkingLot:
    def __init__(self, levels, pricing: PricingStrategy):
        self.levels, self.pricing, self.active = levels, pricing, {}

    def park(self, v: Vehicle) -> Ticket:
        for level in self.levels:
            spot = level.find_spot(v)
            if spot:
                spot.vehicle = v
                t = Ticket(v, spot)
                self.active[t.id] = t
                return t
        raise RuntimeError("Otopark dolu")

    def leave(self, ticket_id: str) -> float:
        t = self.active.pop(ticket_id)
        t.spot.vehicle = None
        return self.pricing.price(t, datetime.now())

4. Tartışmaya açılacak noktalar

  • Desenler: ücret için Strategy, araç oluşturma için Factory, boş yer göstergesi için Observer, ParkingLot için (dikkatli) Singleton.
  • Performans: her katta boyuta göre boş yer kuyrukları (dict[Size, deque]) tutarak aramayı O(1)'e indirmek.
  • Eşzamanlılık: birden fazla giriş kapısı aynı yeri vermesin diye yer atamasında kilit veya atomik işlem.
  • Genişletme: elektrikli araç şarj yerleri, abonelik fiyatlandırması; Open/Closed prensibine uygun mu?
  1. Clean code nedir? Yaygın code smell'ler nelerdir?OrtaOOP & Tasarım DesenleriYazılım Müh.
  2. Dependency Injection nedir? IoC container ne işe yarar?ZorOOP & Tasarım DesenleriYazılım Müh.
  3. Strategy deseni nedir? if/else zincirlerini nasıl ortadan kaldırır?OrtaOOP & Tasarım DesenleriYazılım Müh.
  4. Observer deseni nedir? Gerçek hayatta nerelerde karşımıza çıkar?OrtaOOP & Tasarım DesenleriYazılım Müh.
  5. Factory deseni nedir? Ne zaman kullanılır?OrtaOOP & Tasarım DesenleriYazılım Müh.
  6. Singleton deseni nedir? Neden bazen anti-pattern olarak görülür?ZorOOP & Tasarım DesenleriYazılım Müh.

Bu konuda başka bir soru biliyor musun?

Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.

Soru ekle