Tag: Leadership

  • ASP.NET Core Filters: Stop Repeating the Same Code in Every Controller

    ASP.NET Core Filters: Stop Repeating the Same Code in Every Controller

    When I first started building ASP.NET Core APIs, I noticed a pattern.

    Many controller actions contained the same code:

    • Validate requests.
    • Check permissions.
    • Log execution time.
    • Handle exceptions.
    • Write audit logs.

    The APIs worked.

    But every new endpoint meant copying the same logic again.

    That’s when I discovered Filters.

    I realized they weren’t just another ASP.NET Core feature—they were a way to keep controllers focused on business logic while moving cross-cutting concerns to reusable components.

    What Are Filters?

    Filters allow you to execute code before or after an action method runs.

    Instead of repeating common logic in every controller, you write it once and apply it wherever it’s needed.


    Types of Filters

    Authorization Filter

    Runs first and determines whether the request is authorized.

    Example:

    • Check user permissions.
    • Validate custom authorization rules.

    Resource Filter

    Executes before model binding.

    Useful for:

    • Caching
    • Short-circuiting requests
    • Resource initialization

    Action Filter

    Runs before and after the controller action.

    Common use cases:

    • Input validation
    • Logging
    • Measuring execution time
    • Auditing

    Exception Filter

    Handles exceptions thrown by controller actions.

    Useful for:

    • Logging exceptions
    • Returning consistent error responses

    Result Filter

    Runs before and after the action result is executed.

    Useful for:

    • Modifying response headers
    • Wrapping API responses
    • Adding metadata

    When Should You Use Filters?

    Filters are ideal for logic that applies across multiple endpoints.

    Examples include:

    • Audit logging
    • Request validation
    • Performance monitoring
    • Response formatting
    • Custom authorization

    If you find yourself copying the same code into multiple controllers, it’s often a sign that a filter could help.


    When Should You Avoid Filters?

    Filters aren’t the answer for every problem.

    Choose the right tool for the job:

    • Middleware for application-wide concerns such as authentication, CORS, or request logging.
    • Filters for MVC or API action-specific behavior.
    • Services for business logic.

    Keeping these responsibilities separate leads to a cleaner architecture.


    Final Thoughts

    One lesson changed the way I structure APIs:

    Controllers should coordinate requests—not perform every supporting task themselves.

    Filters help eliminate duplication, improve maintainability, and keep your business logic where it belongs.

  • Background Job Processing: Just Because You Can Do It in the Request Doesn’t Mean You Should

    Background Job Processing: Just Because You Can Do It in the Request Doesn’t Mean You Should

    Early in my career, I had a simple approach.

    A user submitted a request, and the API did everything before returning a response.

    • Save the data.
    • Send an email.
    • Generate a PDF.
    • Upload files.
    • Notify other systems.

    The endpoint worked.

    But it was also slow.

    Then I realized something important:

    Not every task belongs in the request-response cycle.

    Some tasks don’t need to finish before the user receives a response.

    That’s where background job processing becomes valuable.

    What Is Background Job Processing?

    A background job allows your application to offload long-running or non-critical work to execute after the request has completed.

    Instead of making the user wait, the API responds quickly while the background worker processes the remaining tasks.


    What Should Run in the Background?

    Typical examples include:

    • Sending emails or SMS messages.
    • Generating PDF or Excel reports.
    • Processing uploaded files.
    • Creating thumbnails or resizing images.
    • Synchronizing data with external systems.
    • Publishing events or notifications.

    These operations don’t usually need to block the user’s request.


    Benefits

    • Faster API response times.
    • Better user experience.
    • Improved scalability under heavy load.
    • Better resilience when external services are slow.

    Things to Consider

    Background jobs introduce new responsibilities.

    Think about:

    • Retry policies.
    • Error handling.
    • Monitoring and logging.
    • Idempotency to avoid duplicate processing.
    • Queue management.

    Moving work to the background doesn’t remove complexity—it moves it to a different part of the system.


    Common Tools in .NET

    Depending on your requirements, you might choose:

    • Hangfire
    • Quartz.NET
    • Azure Functions
    • Worker Services
    • Message queues such as RabbitMQ or Azure Service Bus

    The best tool depends on your application’s architecture and operational needs.


    Final Thoughts

    One lesson changed how I design APIs:

    Respond as soon as you’ve completed the work the user actually needs.

    Everything else should be evaluated to see whether it belongs in a background job.

    Fast APIs aren’t always the ones that do less work.

    They’re often the ones that do the right work at the right time.

  • 7 EF Core Query Optimization Tips Every .NET Developer Should Know

    7 EF Core Query Optimization Tips Every .NET Developer Should Know

    Entity Framework Core makes database access simple, but it’s also easy to write queries that look correct while performing poorly in production.

    As applications grow, inefficient queries can become one of the biggest performance bottlenecks.

    Here are seven practical techniques I regularly consider when working with EF Core.


    1. Select Only the Columns You Need

    Avoid loading an entire entity if you only need a few properties.

    ❌ Less efficient:

    var users = await context.Users.ToListAsync();
    

    ✅ Better:

    var users = await context.Users
        .Select(u => new
        {
            u.Id,
            u.Name
        })
        .ToListAsync();
    

    Fetching fewer columns reduces network traffic and memory usage.


    2. Use AsNoTracking() for Read-Only Queries

    By default, EF Core tracks every entity it loads.

    If you’re only reading data, disable change tracking.

    var products = await context.Products
        .AsNoTracking()
        .ToListAsync();
    

    This can noticeably improve performance for read-heavy operations.


    3. Avoid the N+1 Query Problem

    This is a common performance issue.

    Instead of triggering additional queries for related data, load it efficiently.

    var orders = await context.Orders
        .Include(o => o.Customer)
        .ToListAsync();
    

    Or project only the data you actually need.


    4. Filter Early

    Push filtering to the database.

    var activeUsers = await context.Users
        .Where(u => u.IsActive)
        .ToListAsync();
    

    Don’t retrieve unnecessary rows and filter them in memory.


    5. Paginate Large Result Sets

    Avoid returning thousands of records at once.

    var customers = await context.Customers
        .OrderBy(c => c.Id)
        .Skip(page * pageSize)
        .Take(pageSize)
        .ToListAsync();
    

    Pagination improves both application performance and user experience.


    6. Check the Generated SQL

    EF Core generates SQL for you—but you should still know what it’s executing.

    Use:

    var sql = query.ToQueryString();
    

    Reviewing the generated SQL helps identify unnecessary joins, filters, or inefficient queries before they reach production.


    7. Create the Right Database Indexes

    Even the best EF Core query can perform poorly without proper indexing.

    Frequently filtered or joined columns should be indexed appropriately.

    Remember:

    EF Core generates SQL. SQL Server executes it.

    Database design still matters.


    Final Thoughts

    Optimizing EF Core isn’t about replacing it with raw SQL.

    It’s about understanding how your LINQ queries translate into SQL and ensuring the database performs as little work as necessary.

    A few simple habits can make a significant difference:

    • Project only what you need.
    • Use AsNoTracking() for read-only queries.
    • Avoid N+1 queries.
    • Filter early.
    • Paginate large datasets.
    • Inspect generated SQL.
    • Design proper indexes.

    Small optimizations applied consistently often produce the biggest improvements.

  • How Do You Work Effectively with Cross-Functional Teams?

    How Do You Work Effectively with Cross-Functional Teams?

    Building great software isn’t just about writing clean code.

    It’s about collaborating with people from different disciplines—product managers, UI/UX designers, QA engineers, DevOps engineers, business analysts, and stakeholders.

    As a software engineer, your success depends not only on technical skills but also on how well you work with cross-functional teams.

    1. Start with a Shared Understanding

    Before writing code, make sure everyone agrees on:

    • The business goal
    • The user problem
    • The expected outcome
    • Success criteria

    When the team shares the same vision, misunderstandings are reduced.


    2. Communicate Clearly

    Avoid assuming everyone understands technical jargon.

    Instead:

    • Explain technical decisions in simple language.
    • Ask questions to clarify requirements.
    • Share updates proactively.

    Good communication prevents costly rework.


    3. Involve the Right People Early

    Don’t wait until development is complete to involve other teams.

    For example:

    • Discuss feasibility with DevOps before deployment.
    • Review designs with UI/UX before implementation.
    • Collaborate with QA while defining acceptance criteria.

    Early collaboration saves time later.


    4. Respect Different Perspectives

    Every role brings unique expertise.

    • Product Managers focus on business value.
    • Designers focus on user experience.
    • QA focuses on quality and edge cases.
    • DevOps focuses on reliability and deployment.
    • Developers focus on technical implementation.

    Listening to each perspective leads to better decisions.


    5. Handle Feedback Professionally

    Code reviews, testing feedback, and design changes are opportunities to improve—not personal criticism.

    A collaborative mindset builds trust within the team.


    6. Be Transparent About Risks

    If you identify:

    • Technical debt
    • Performance concerns
    • Security risks
    • Timeline impacts

    Raise them early.

    Surprises late in the project are much harder to manage.


    7. Focus on the Shared Goal

    Cross-functional collaboration isn’t about proving one team is right.

    It’s about delivering value to users.

    When disagreements arise, return to the shared objective and make decisions based on what’s best for the product.


    Final Thoughts

    The best software isn’t built by individual developers—it’s built by teams that communicate, collaborate, and trust one another.

    Strong technical skills may help you become a good developer.

    Strong collaboration skills help you become a great engineer.

  • User বারবার Send Button চাপল, আর Customer-এর টাকা দুইবার কেটে গেল! এটা কীভাবে প্রতিরোধ করবেন?

    User বারবার Send Button চাপল, আর Customer-এর টাকা দুইবার কেটে গেল! এটা কীভাবে প্রতিরোধ করবেন?

    ধরুন, আপনি একটি Payment API তৈরি করেছেন।

    একজন User “Pay Now” বাটনে চাপ দিলেন।

    কিন্তু Server একটু ধীর (Slow)।

    User ভাবলেন,

    “হয়তো Click হয়নি!”

    তিনি আবার Button চাপলেন।

    তারপর আবার।

    কয়েক সেকেন্ড পরে…

    Customer Support থেকে ফোন—

    “একই Payment-এর জন্য Customer-এর টাকা দুইবার কেটে গেছে!”

    এখন প্রশ্ন হলো—

    সমস্যাটা User-এর, নাকি System-এর?

    আমার মতে, System-এর।

    কারণ একটি ভালো Payment System কখনোই একই Payment একাধিকবার Process করবে না।


    প্রথম প্রতিরক্ষা: Frontend

    Frontend থেকেই Duplicate Request কমানো যায়।

    যেমন—

    • Button Click করার পর Disable করে দেওয়া।
    • Loading Spinner দেখানো।
    • Request Complete না হওয়া পর্যন্ত দ্বিতীয় Click Block করা।

    এতে অনেক Duplicate Request শুরুতেই বন্ধ হয়ে যায়।

    কিন্তু…

    শুধু Frontend-এর উপর নির্ভর করা যাবে না।

    কারণ—

    • User Page Refresh করতে পারে।
    • Network Retry হতে পারে।
    • Mobile App একই Request আবার পাঠাতে পারে।
    • কোনো Bot Request পাঠাতে পারে।

    তাই আসল নিরাপত্তা Backend-এ থাকতে হবে।


    দ্বিতীয় প্রতিরক্ষা: Idempotency Key

    প্রতিটি Payment Request-এর সাথে একটি Unique Id পাঠানো হয়।

    যেমন—

    Idempotency-Key: 7f4c9d...
    

    যদি একই Key আবার আসে,

    Server নতুন Payment Process করবে না।

    আগের Result-ই Return করবে।


    তৃতীয় প্রতিরক্ষা: Database Constraint

    Database-এ এমনভাবে Design করুন,

    যাতে একই Transaction Reference দুইবার Insert-ই করা না যায়।

    যেমন—

    • PaymentReference
    • OrderId
    • TransactionId

    এসবের উপর Unique Constraint থাকতে পারে।

    Database অনেক সময় শেষ নিরাপত্তা দেয়।


    চতুর্থ প্রতিরক্ষা: Transaction

    Payment-এর গুরুত্বপূর্ণ Operation-গুলো Transaction-এর মধ্যে করুন।

    যাতে মাঝপথে কোনো সমস্যা হলে Partial Data Save না হয়।


    পঞ্চম প্রতিরক্ষা: Distributed Lock (যেখানে প্রয়োজন)

    যদি Multiple Server একই Payment Process করতে পারে,

    তাহলে Redis Distributed Lock-এর মতো সমাধান ব্যবহার করা যেতে পারে।

    এতে একই সময়ে একটি Payment শুধুমাত্র একটি Server Process করবে।


    সবচেয়ে গুরুত্বপূর্ণ শিক্ষা

    একজন User একই Request একাধিকবার পাঠাতে পারেন।

    Network একই Request Retry করতে পারে।

    Gateway একই Callback আবার পাঠাতে পারে।

    এসবই স্বাভাবিক।

    অস্বাভাবিক হলো—

    System সেই Request-গুলোকে নতুন Payment হিসেবে ধরে আবার টাকা কেটে ফেলছে।

    একটি ভালো Payment System-এর লক্ষ্য হওয়া উচিত—

    “One business operation = One successful payment.”

    যতবার Request আসুক না কেন।

  • ম্যানেজার হঠাৎ বললেন, “এই Project-এর Estimation করে দেন!” — তখন কী করবেন?

    ম্যানেজার হঠাৎ বললেন, “এই Project-এর Estimation করে দেন!” — তখন কী করবেন?

    সকালের Stand-up Meeting শেষ।

    হঠাৎ ম্যানেজার বললেন,

    “Faiz, এই নতুন Project-এর একটা Estimation আজকেই লাগবে।”

    প্রথম প্রতিক্রিয়া কী হবে?

    অনেকেই তাড়াহুড়ো করে একটা সংখ্যা বলে দেন—

    “মনে হয়… ২ সপ্তাহ লাগবে।”

    কিন্তু একজন অভিজ্ঞ Software Engineer জানেন,

    Estimation মানে Guess করা নয়।

    Estimation মানে হলো, বর্তমান তথ্যের ভিত্তিতে একটি যৌক্তিক পূর্বাভাস (Forecast)।


    আমি কীভাবে শুরু করি?

    প্রথমেই আমি একটি প্রশ্ন করি—

    Requirement কি পুরোপুরি পরিষ্কার?

    যদি Requirement পরিষ্কার না হয়, তাহলে কোনো Estimation-ই নির্ভুল হবে না।


    এরপর Project-টাকে ছোট ছোট অংশে ভাগ করি

    একটি বড় Feature-এর Estimation করা কঠিন।

    কিন্তু যদি এটিকে ভাগ করি—

    • Authentication
    • Database Design
    • API Development
    • Frontend Integration
    • Unit Testing
    • Deployment

    তাহলে Estimation অনেক বাস্তবসম্মত হয়।


    Unknown বিষয়গুলো আলাদা করি

    সব Project-এই কিছু Unknown থাকে।

    যেমন—

    • Third-party API Integration
    • নতুন Technology
    • Client-এর পরিবর্তিত Requirement

    এসব ঝুঁকি (Risk) আগে থেকেই চিহ্নিত করলে Estimation আরও বাস্তবসম্মত হয়।


    Buffer রাখতে ভুলবেন না

    একটি Project কখনোই শুধুমাত্র Coding নয়।

    এর সাথে থাকে—

    • Code Review
    • Bug Fix
    • Testing
    • Meeting
    • Deployment
    • Production Support

    শুধু Coding Time ধরে Estimation করলে প্রায়ই Deadline মিস হয়।


    সবচেয়ে বড় ভুল

    অনেক সময় আমরা Pressure-এর কারণে বলি—

    “হ্যাঁ, হয়ে যাবে।”

    কিন্তু বাস্তবে Requirement না বুঝে দেওয়া Estimation পুরো Team-এর জন্য সমস্যার কারণ হতে পারে।

    একজন Professional Engineer প্রয়োজনে বলেন—

    “আমি Requirement Review করে আজ বিকেলের মধ্যে একটি বাস্তবসম্মত Estimation জানাচ্ছি।”

    এটা দুর্বলতা নয়, বরং Professionalism।


    আমার শেখা একটি বিষয়

    বছরের পর বছর কাজ করে একটি বিষয় বুঝেছি—

    ভুল Estimation দেওয়ার চেয়ে, একটু সময় নিয়ে সঠিক Estimation দেওয়া অনেক ভালো।

    কারণ Deadline মিস করলে শুধু Project নয়, Team-এর বিশ্বাসও ক্ষতিগ্রস্ত হয়।

    শেষ কথা

    Estimation কোনো প্রতিশ্রুতি (Promise) নয়।

    এটি হলো একটি Forecast, যা বর্তমান তথ্যের উপর ভিত্তি করে তৈরি হয়।

    আর একজন ভালো Software Engineer-এর কাজ শুধু দ্রুত উত্তর দেওয়া নয়, বরং তথ্যভিত্তিক এবং বাস্তবসম্মত উত্তর দেওয়া।

  • Control Makes People Behave. Autonomy Makes People Engage.

    Control Makes People Behave. Autonomy Makes People Engage.

    A team can follow rules and still lack ownership.

    Why?

    Because compliance and commitment are not the same thing.

    Control can create short-term results:

    ✅ People follow instructions

    ✅ Tasks are completed on time

    ✅ Processes are maintained

    But excessive control can also create:

    ❌ Fear of making decisions

    ❌ Less creativity

    ❌ Waiting for approval instead of taking ownership

    ❌ A “just do what I was told” mindset

    Autonomy creates a different environment.

    When people have trust and freedom to make decisions:

    ✅ They think beyond their assigned tasks

    ✅ They take responsibility for outcomes

    ✅ They bring new ideas

    ✅ They feel connected to the team’s success

    For example:

    A manager says:

    “Complete this task exactly as I described.”

    The employee focuses on finishing the task.

    A better approach:

    “Here is the goal. Choose the best way to achieve it.”

    The employee starts thinking like an owner.

    Good leadership is not about controlling every action.

    It is about providing:

    • Clear expectations
    • The right direction
    • Necessary support
    • Freedom to execute

    The goal is not to create people who only follow instructions.

    The goal is to build people who can think, decide, and contribute.

    💡 Great teams are not built on control alone.

    They are built on trust with accountability.

    👇 What creates better teams in your experience?

    More control or more autonomy?

    ♻️ If you found this helpful, feel free to repost and share it with your network.

    👉 Follow Faiz Ahmed Rasel for more .NET tips, tutorials, and deep dives.

    #Leadership #TeamManagement #ProfessionalGrowth #SoftwareEngineering #CareerDevelopment