From University to Enterprise to AI: A Software Developer's Journey

January 7, 2025

I started with simple Java programs in university, emerged into the complex world of enterprise supply chain software, and now pursuing the frontier of AI development. Here is a reflection of my journey, complete with code snippets that characterize the phases along the way.

University Days: Learning the Basics

Section Logo

My coding journey began in university with Java. Like many students, I started with the classic:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

One of my first side projects was a simple inventory management system:

public class InventoryItem {
    private String name;
    private int quantity;
    private double price;

    public InventoryItem(String name, int quantity, double price) {
        this.name = name;
        this.quantity = quantity;
        this.price = price;
    }

    public boolean isInStock() {
        return quantity > 0;
    }

    public double getTotalValue() {
        return quantity * price;
    }
}

Little did I know this simple class would foreshadow my future in supply chain software!

Enterprise Development: Scaling Up

Section LogoSection LogoSection LogoSection Logo

Moving into enterprise development, i got thrown into a large codebase that had evolved over many years. My employer had been developing a bespoke solution for a large Swedish furnishing company. The solution was running very large SQL transformation jobs, taking numerous ERP systems as input to build up network optimization and inventory management models. As a result of an ever increasing scope and business logic requirements, the codebase had become unnecerasily complex with procedures wrapping around procedures.

SELECT 
    w.warehouse_id,
    w.name AS warehouse_name,
    i.item_id,
    i.description,
    i.quantity_on_hand,
    COALESCE(o.pending_orders, 0) AS pending_orders,
    (i.quantity_on_hand - COALESCE(o.pending_orders, 0)) AS available_stock,
    s.supplier_name,
    s.lead_time_days,
    CASE 
        WHEN i.quantity_on_hand = 0 THEN 'OUT_OF_STOCK'
        WHEN i.quantity_on_hand < i.reorder_point THEN 'LOW_STOCK'
        ELSE 'SUFFICIENT_STOCK'
    END AS stock_status,
    ROUND(
        (i.quantity_on_hand::DECIMAL / NULLIF(i.max_capacity, 0)) * 100, 
        2
    ) AS capacity_utilization_pct
FROM 
    warehouses w
    INNER JOIN inventory i ON w.warehouse_id = i.warehouse_id
    LEFT JOIN (
        SELECT 
            warehouse_id,
            item_id,
            SUM(quantity) AS pending_orders,
            COUNT(DISTINCT customer_id) AS unique_customers,
            MAX(created_at) AS latest_order_date
        FROM orders 
        WHERE status = 'PENDING'
            AND created_at >= NOW() - INTERVAL '30 days'
        GROUP BY warehouse_id, item_id
    ) o ON i.warehouse_id = o.warehouse_id 
        AND i.item_id = o.item_id
    LEFT JOIN suppliers s ON i.primary_supplier_id = s.supplier_id
    LEFT JOIN warehouse_zones z ON w.warehouse_id = z.warehouse_id
WHERE
    i.quantity_on_hand < i.reorder_point
    AND w.is_active = true
    AND (
        w.maintenance_schedule IS NULL 
        OR w.maintenance_schedule > CURRENT_DATE
    )
    AND z.temperature_celsius BETWEEN i.min_storage_temp AND i.max_storage_temp
HAVING 
    COALESCE(o.unique_customers, 0) >= 3
    OR i.quantity_on_hand <= i.safety_stock_level
ORDER BY
    w.warehouse_id,
    stock_status DESC,
    i.quantity_on_hand ASC,
    s.lead_time_days ASC;

This experience taught me an important lesson about code isolation and testability - always design for testability from the start, because you rarely get the time to fix it later.

Also part of the learning experience came from working with Git and Azure DevOps in a large enterprise team. Developing features is more than writing performant and maintainable code. It's also about organizing development efforts for the solution work now and in the future.

The AI Frontier: Where I Am Now

Section LogoSection LogoSection LogoSection LogoSection LogoSection Logo

For the past six months, I’ve been building agentic coding software. It's not just about automation anymore — it's about building systems that can understand context, reason over intent, and write coherent code. Here's an example of how one of my agents uses prompt templates to dynamically request completions from an LLM:

interface PromptTemplate {
    systemPrompt: string;
    userPrompt: string;
}

interface CompletionAgent {
    model: LLMClient;
    template: PromptTemplate;

    async completeFunction(name: string, description: string, signature: string): Promise<string> {
        const prompt = `
${this.template.systemPrompt}

${this.template.userPrompt
    .replace("{function_name}", name)
    .replace("{description}", description)
    .replace("{signature}", signature)}
        `;

        const response = await this.model.complete({
            prompt,
            temperature: 0.7,
            maxTokens: 256,
        });

        return response.code;
    }
}

const agent = new CompletionAgent({
    model: openAIClient,
    template: {
        systemPrompt: "You are an expert software engineer. Write idiomatic, efficient TypeScript functions.",
        userPrompt: "Given a function called `{function_name}` that {description}, implement it. Signature:\n{signature}"
    }
});

const result = await agent.completeFunction(
    "filterValidEmails",
    "filters out invalid email addresses from a list",
    "function filterValidEmails(emails: string[]): string[]"
);

Looking Ahead

The emergence of AI in software development brings new challenges and opportunities. It's an exciting time to be in this field, as we figure out how to effectively combine traditional programming practices with these new capabilities. The technology landscape will continue to evolve. What matters is building a strong foundation in software engineering principles while staying adaptable to new tools and approaches as they emerge.