Categories
Uncategorized

Lessons in Teamwork and Leadership

Having worked professionally as a software developer for several years, I’ve been part of multiple teams where development workflows, responsibilities, and expectations were well understood. Across different teams, including at my current job, there has always been a common framework for how work gets done, with clear expectations around code quality, collaboration, and accountability that team members consistently follow. There has also always been an unambiguous leader–someone to make final decisions, set expectations and priorities, and keep things on track.

This project has presented a very different dynamic, and it has made me realize how much I took for granted the structure and leadership that helped my previous teams run smoothly. I initially assumed that a well-functioning development process would emerge organically, but I now recognize the importance of deliberately establishing structure and alignment. Without clear expectations, work is done inconsistently, best practices are an afterthought, and accountability is hard to maintain.

As the project progressed, I found myself needing to take on more of a leadership role to help establish the structure we were lacking. This has been an uncomfortable shift for me. I’ve always preferred to focus on my own work rather than trying to manage others, and I don’t at all enjoy feeling like I’m telling people what to do. But without clear expectations or direction, the team struggled to stay aligned, and progress suffered. This wasn’t anyone’s fault–everyone works differently, has different priorities, and brings a unique level of experience to the table. I remember what it was like to work on a development team for the first time–how overwhelming it felt to navigate unfamiliar tools, processes, and expectations. I had no idea what was going on half the time, and I relied heavily on the more experienced developers around me to provide guidance and structure. Now, for the first time, I find myself on the other side of that equation.

One of the biggest lessons I’ve taken away is that, while high standards are important, focusing too much on perfection can slow progress and create unnecessary friction. At the end of the day, working software is far more valuable than perfect software. Keeping momentum is key, and if something truly needs refinement, I can always revisit it later or fork the project once it’s complete. I also feel that I’ve grown significantly as a developer over the course of this project. Unlike other projects where I’ve focused more narrowly on specific tasks or smaller parts of larger systems, this time I’m involved in everything (backend, frontend, DevOps, project management, etc.) and understand the project from top to bottom. This has helped me develop a stronger sense of how to make architectural decisions, troubleshoot complex issues, and ensure that different components integrate smoothly.

This experience has given me a new perspective on what makes teams and projects successful. These are some of the most important lessons I’ve learned along the way:

  1. Leadership is about taking responsibility
    Leadership often emerges out of necessity rather than position. Even when roles are loosely defined, someone has to take ownership to keep things on track.
  2. Structure doesn’t emerge on its own
    Clear workflows and expectations don’t happen by accident–they have to be deliberately established. Without them, even talented teams can struggle with inefficiencies, misalignment, and stalled progress.
  3. Effective teamwork isn’t just about individual contributions–understanding the big picture is crucial
    A successful project isn’t just a collection of completed tasks–it’s a system that needs to function as a whole. Making sure everything integrates smoothly is just as important as getting individual pieces right.
  4. Every team operates differently, and adaptability is crucial
    What works in a highly structured, experienced team might not apply in a more loosely defined environment. Recognizing those differences and adjusting expectations is key to being an effective team member.
  5. Progress > perfection
    Chasing the ideal version of something can often slow progress. Prioritizing working software keeps momentum going, and if something really matters, it can always be revisited later.

All in all, this project has been one of the most valuable learning experiences I’ve had. It has pushed me outside my comfort zone, forcing me to take on responsibilities I wouldn’t have otherwise. I’ve gained a deeper appreciation for what it takes to keep a project moving forward and the immense value of clear communication, shared expectations, and collaborative problem-solving in building successful software.

Categories
Uncategorized

Reflections on Our Tech Stack Evolution

As mentioned in previous posts, the primary technology that we are using for our application is Laravel. We had initially planned to build on top of OWASP’s Vulnerable Web App, which is written in PHP and uses a traditional LAMP stack. After exploring the codebase, I realized that modifying it to meet our requirements would likely take more effort than starting fresh. This led me to explore Laravel as an alternative, and I’m very glad that I did.

My background is primarily in backend development, working with Go and PostgreSQL, and while I’ve been involved with some full-stack development in the past, most of those experiences involved working on small parts of larger systems. What I particularly appreciate about Laravel is how it provides powerful abstractions that make building full-featured web applications approachable, even for someone with limited frontend experience. In less than a day, I was able to create a proof-of-concept with a landing page, navigation bar, authentication system, and role-based access control, which would have taken significantly longer without Laravel’s built-in components.

As our development has progressed, I’ve been learning a lot more about Laravel’s architectural patterns and best practices. Recently, we’ve been focusing on improving our code quality by applying these principles throughout our codebase. For example, we were initially implementing all of our logic inside of controller classes (validation logic, business logic, database queries, etc.). This approach violated the single responsibility principle and made our controllers difficult to maintain and test. We’ve since started breaking these responsibilities apart into more focused classes. Business logic now lives in service classes, validation rules in form request classes, and data transformations in presenters. This has made our code much more organized and testable.

Docker has been another key technology in our stack, though it has presented some challenges. We had to spend some time ironing out issues with our local containerized deployment setup, and while this took some effort to get right, the investment has proven worthwhile. Team members can now reliably spin up identical development environments regardless of their local setup.

For the frontend, we chose to use Laravel’s Blade templating system for its simplicity and ease of use. While Blade has served our needs well, I sometimes wonder if we should have opted for a more modern frontend framework like React. When setting up a Laravel project, you can choose between different frontend stacks including Blade templates, React, or Vue.js. Given my limited frontend experience, Blade templates seemed like the safest choice, but React’s component-based architecture might have made it easier to build more interactive and dynamic features.

For styling, we are using Tailwind CSS. Since none of us have extensive experience with frontend styling, we would have faced a learning curve regardless of which styling solution we chose. Tailwind has proven to be a reasonable choice, offering a straightforward way to create consistent layouts.

We’ve been using PHPUnit for our testing needs. It took a bit of effort to figure out how to properly use the framework, but now that we’ve gotten the hang of it, it seems relatively straightforward. I think it will be very valuable for verifying our application’s behavior and making sure we aren’t introducing regressions as we continue to build out and improve the codebase.

We’re getting very close to having all of the major features of the application finished and well-tested, at which point we will start to focus on identifying and documenting various vulnerabilities in our application. We will likely use tools like OWASP ZAP, SQLmap, and Metasploit in this process. I have no experience with tools like these, so I am looking forward to learning how to use them.

All-in-all, I’m pleased with the technology choices we’ve made. Laravel has been particularly enjoyable to work with, and while the containerized deployment with Docker took some time to get right, it’s proven to be very useful in our development process. The only change I might consider would be using React instead of Blade templates for building more interactive features, but that’s a minor consideration given how well everything has worked together.

Categories
Uncategorized

Clean Code with Laravel

We are fully in the swing of development now, so I’ve been thinking a lot about code quality lately. This is the first time I’ve ever used PHP or Laravel, so I’m still learning about how everything works and what the best practices are. I know that there must be a lot of things that I could improve. Laravel made it easy to get started and develop a prototype quickly, but now I’m much more focused on making sure the codebase is clean, maintainable, and scalable as we continue to add features.

The prompt for this post asks us to read an article on clean code, and another on code smells. Since I’m working with Laravel, I looked for articles that were specifically about clean code and code smells in Laravel. The articles that I found to be most helpful were Understanding Code Smells in PHP and Laravel by Sohag Hasan and Writing Clean Code in Laravel by Manish Kumar.

One thing I want to start doing, which was mentioned in both articles and was something I didn’t know about, is to use service classes to encapsulate logic and keep controllers small. We have only implemented a relatively small amount of “business” logic at this point, so excessively large classes aren’t a huge problem yet, but I can see how it would be almost an inevitability without deliberate efforts to separate concerns.

I found a controller class in our codebase that does have some logic that seems like it could be moved into a service class. The controller, named FeedbackController, handles listing, storing, and searching patient feedback. It also handles creating a new patient if feedback is submitted for a patient that does not exist.

class FeedbackController extends Controller
{
    public function index()
    {
        $feedback = PatientFeedback::orderBy('created_at', 'desc')->get();
        return view('feedback.index', compact('feedback'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'fname' => 'required|max:255',
            'lname' => 'required|max:255',
            'feedback' => 'required'
        ]);

        $validated['fname'] = htmlspecialchars($validated['fname']);
        $validated['lname'] = htmlspecialchars($validated['lname']);

        $patient = Patient::where('first_name', $validated['fname'])
            ->where('last_name', $validated['lname'])
            ->first();

        if (!$patient) {
            $patient = Patient::create([
                'first_name' => $validated['fname'],
                'last_name' => $validated['lname']
            ]);
        }

        PatientFeedback::create([
            'patient_id' => $patient->patient_id,
            'feedback' => $validated['feedback']
        ]);

        return redirect()->route('feedback')
            ->with('success', 'Feedback added successfully!');
    }

    public function search(Request $request)
    {
        $name = $request->input('search_name');
        $feedback = PatientFeedback::whereHas('patient', function ($query) use ($name) {
            $query->where('first_name', 'like', "%{$name}%")
                ->orWhere('last_name', 'like', "%{$name}%");
        })->orderBy('created_at', 'desc')->get();

        return view('feedback.index', compact('feedback'))->with('search_name', $name);
    }
}

We could break out the logic for validation, storing, listing, and searching into a dedicated service class like this:

class FeedbackService
{
    public function validateFeedback(array $data)
    {
        $validator = Validator::make($data, [
            'fname' => 'required|max:255',
            'lname' => 'required|max:255',
            'feedback' => 'required',
        ]);

        if ($validator->fails()) {
            throw new \Illuminate\Validation\ValidationException($validator);
        }

        $data['fname'] = htmlspecialchars($data['fname']);
        $data['lname'] = htmlspecialchars($data['lname']);

        return $data;
    }

    public function saveFeedback(array $data)
    {
        $patient = Patient::firstOrCreate(
            ['first_name' => $data['fname'], 'last_name' => $data['lname']],
            ['first_name' => $data['fname'], 'last_name' => $data['lname']]
        );

        return PatientFeedback::create([
            'patient_id' => $patient->patient_id,
            'feedback' => $data['feedback']
        ]);
    }

    public function getAllFeedback()
    {
        return PatientFeedback::orderBy('created_at', 'desc')->get();
    }

    public function searchFeedbackByName(string $name)
    {
        return PatientFeedback::whereHas('patient', function ($query) use ($name) {
            $query->where('first_name', 'like', "%{$name}%")
                  ->orWhere('last_name', 'like', "%{$name}%");
        })->orderBy('created_at', 'desc')->get();
    }
}

And then the FeedbackController would be quite a bit simpler:

class FeedbackController extends Controller
{
    protected $feedbackService;

    public function __construct(FeedbackService $feedbackService)
    {
        $this->feedbackService = $feedbackService;
    }

    public function index()
    {
        $feedback = $this->feedbackService->getAllFeedback();
        return view('feedback.index', compact('feedback'));
    }

    public function store(Request $request)
    {
        try {
            $this->feedbackService->saveFeedback($request->all());
            return redirect()->route('feedback')
                ->with('success', 'Feedback added successfully!');
        } catch (\Illuminate\Validation\ValidationException $e) {
            return redirect()->back()->withErrors($e->validator)->withInput();
        }
    }

    public function search(Request $request)
    {
        $name = $request->input('search_name');
        $feedback = $this->feedbackService->searchFeedbackByName($name);

        return view('feedback.index', compact('feedback'))->with('search_name', $name);
    }
}

This way, the controller focuses on handling HTTP requests, while the service class encapsulates the logic for managing feedback. It makes the code cleaner and also makes it easier to test each layer independently.

I would like for us to stop putting so much logic in our controllers. It hasn’t become a huge problem yet, but it would be good to get into the habit of keeping as much logic out of the controllers as possible. Another way, beside service classes, to accomplish this (which I also just learned about) it to use Laravel’s form request classes for validation logic.

For example, in our FeedbackController, the store method currently has inline validation and sanitization:

public function store(Request $request)
{
    $validated = $request->validate([
        'fname' => 'required|max:255',
        'lname' => 'required|max:255',
        'feedback' => 'required'
    ]);

    $validated['fname'] = htmlspecialchars($validated['fname']);
    $validated['lname'] = htmlspecialchars($validated['lname']);

    // ...
}

If we make a new request class to encapsulate this logic, Laravel will automatically validate the request when the class is type-hinted in the controller.

class FeedbackRequest extends FormRequest
{
    public function rules()
    {
        return [
            'fname' => 'required|max:255',
            'lname' => 'required|max:255',
            'feedback' => 'required',
        ];
    }

    protected function prepareForValidation()
    {
        $this->merge([
            'fname' => htmlspecialchars($this->input('fname')),
            'lname' => htmlspecialchars($this->input('lname')),
        ]);
    }
}

With that in place, the FeedbackController‘s store method is much simpler:

public function store(FeedbackRequest $request)
{
    $validated = $request->validated(); // Automatically validated and sanitized
    $this->feedbackService->saveFeedback($validated);

    return redirect()->route('feedback')
        ->with('success', 'Feedback added successfully!');
}

Writing code like this is beneficial because it promotes separation of concerns, reusability, and maintainability.

Categories
Uncategorized

Vulnerable Web App Progress

When development began a few weeks ago, we had just moved the Laravel proof-of-concept into our main repository. My fist order of business was to clean up the codebase, removing unneeded Laravel bloat and making sure the application had a lean foundation. Laravel is great, but the initial scaffolding included some features and files that our project didn’t need, so I spent some time trimming unnecessary components and simplifying the configuration. Because some team members aren’t as experienced with web development, I wanted to make the codebase as straightforward as possible.

Initially, some team members were having problems deploying the application via Docker. This turned out to be an issue with where npm run build was creating manifest.json inside of the application container; the file was sometimes being created in public/build/.vite/ and sometimes in public/build/. It was a seemingly simple issue, but none of the available configuration options were resolving it, and it was unclear why it was behaving differently on different systems. In the end, I wrote a post-build script to make sure the file is available at the expected location. With this, all team members are able to deploy the application without issue. While doing this, I also made general improvements and optimizations to our Docker configuration.

After cleaning up the codebase and resolving the deployment issues, I decided to finish setting up the core application infrastructure, including routes, models, controllers, and the database schema. Because these elements are fundamental to the project and will be used by everyone on the team, I wanted to establish a consistent foundation upfront. My goal was to create a shared framework that would streamline development and minimize potential merge conflicts. My hope is that the early establishment of these elements will make it easier for everyone to work on their respective features without worrying about conflicting changes to the fundamental structure of the application.

Specifically, I established a consistent pattern for endpoint organization, mapped out the main endpoints based on the application requirements, and included placeholders for future features. This pattern involves keeping all endpoint methods in associated controllers and grouping endpoints logically by resource. To do this, I needed to create all of the controllers in advance. For planned features that have not been implemented, I included placeholder methods within the controllers. This should allow team members to simply update the methods in the controllers corresponding to the features they own and update the routes to map to those endpoints.

When I created the proof-of-concept, I had only created a user table, but our schema requires a couple of additional tables. Because the database had already been designed, will be used by everyone on the team, and only needed to be implemented, I added migrations to create the additional tables. I also added a factory and seeder to fill the database with fake users. During our next development period, I want to add some unit tests for the authentication and access control systems, and then get started with some penetration testing.

Categories
Uncategorized

Kicking Off the Website Security Research Project

Since my first post a little over a month ago, projects have been assigned, requirements gathered, designs drafted, and initial development has kicked off. I was fortunate to be assigned to my top choice, the Website Security Research Project, and am working with a very capable team to deliver something exceptional.

The project involves building a simple web application and adopting an iterative process of performing penetration testing on the application infrastructure, hardening the application security according to test results, and creating detailed documentation on detected vulnerabilities, methods used to exploit those vulnerabilities, and strategies to improve the application’s security. By the time we are finished, we will have an application that can be used by anyone with an interest in website security to learn about common vulnerabilities, exploitation methods, and recommended security practices. Our goal is to enable users of any skill or experience level to easily deploy the application and follow our documentation to gain useful, hands-on experience in identifying, exploiting, and mitigating common web security vulnerabilities. We will implement both secure and insecure versions of each web page in the application and allow users to toggle individual vulnerabilities on or off, providing them an opportunity to directly observe the impacts of specific vulnerabilities and security measures on the system. My team has decided to build this application as a simulated health plan portal with various exploitable features, including text inputs for various types of injection attacks and a role-based access control system for demonstrating broken access control vulnerabilities.

Because the focus of our project is on security testing and hardening rather than application development, we initially planned to build the application on top of OWASP’s Vulnerable-Web-App repository, which uses a LAMP stack (Linux, Apache, MySQL, and PHP), to speed up the development phase. While doing research, I forked the Vulnerable-Web-App repository to see how difficult it would be to modify to meet our requirements. I can’t tell you how happy I am that I did this when I did, because I realized very quickly that modifying the existing codebase would almost certainly require more effort than simply starting from scratch. The majority of the OWASP code is not easily reusable for our design, and adapting it to our project’s needs would introduce unnecessary complexity. After discovering this, I began exploring other ways we might be able to speed up the development of the application’s core infrastructure.

During my research, I came across Laravel, a PHP framework with a robust set of features for developing modern web applications. I was drawn to Laravel by its rapid prototyping capabilities and scalable architecture. It offers an array of pre-built components, a simple but powerful routing engine, an ORM, a built-in authentication and authorization system, an extensive package ecosystem, and built-in features for automated testing and job processing, all of which we can leverage speed up the development process. Perhaps more importantly, it provides useful abstractions that will allow our code to be more modular, maintainable, and adaptable as the application evolves. After exploring Laravel’s features, I decided to create a proof-of-concept to better understand its potential and to pitch its value to my team. In one afternoon/evening, I was able to create a landing page, navigation bar, a fully functional authentication system (complete with profile creation, login, logout, and profile update features), and a role-based access control system with an admin page for setting user roles. I was sold by this experience, and when I showed my team what I had been able to accomplish, they were fully on-board.

My proof-of-concept has now become the foundation upon which we will build the rest of our application. The immediate next steps will involve setting up our repository and project infrastructure to ensure optimal development operations and collaboration among team members. This will include integrating with GitHub Actions to automate our workflows, enabling automatic testing, building, and linting of the application on each push to the repository. This will help make sure our application remains stable and does not regress. We’ll also need to establish a clear system for making changes and adding new features. We have some ideas and plans around how to do this, but there are still some specifics to work out. Once we’ve done this, we can implement the core data models that will be used throughout the system and begin to build out the remaining infrastructure. After the application infrastructure is in place, we’ll shift focus to penetration testing, application hardening, and documentation.

I’ve already learned quite a bit in the initial stages of this project. I have been involved with full-stack development on a handful of projects in the past, but most of these experiences have involved only a small part of a larger system. I have rarely been involved with building and maintaining entire web applications from scratch, and I have never built anything with PHP, so creating the Laravel proof-of-concept was an enlightening experience. In addition to learning new technical skills, I’ve been getting plenty of opportunities to practice my soft skills. Working on something as important as the capstone project, with a team operating in a flat structure without a designated lead, has highlighted how essential skills like clear communication and adaptability are for effective collaboration in a self-managed environment. These skills are, of course, important in any team environment, but in my experience, a clear hierarchy of authority often reduces friction, streamlines decision-making, and helps to keep everyone aligned and moving in the right direction. Without a team lead, it takes some effort to find an optimal balance between taking initiative and creating space for others to contribute. My team has been great, though, and so far, this has been a valuable experience. I’m very much looking forward to seeing what we can build together.

Thanks for reading. I look forward to sharing more updates as the project progresses.

Categories
Uncategorized

Introduction

Hello! My name is Cody Ray. I currently live in Bend, Oregon (PST/PDT). Lately, I’ve been doing a lot of hiking and fly fishing. When the weather turns, I enjoy reading fiction and playing guitar.

I became interested in software in my early 20s. Before that, I worked as a welder, building trailers. That experience sparked my interest in becoming an engineer, so I enrolled in a few community college courses on a Mechanical Engineering track. One of those courses was Intro to Engineering Computing, which taught MATLAB. This was my first exposure to programming, and I found it so interesting that I switched my major to Computer Science by the end of the term.

After that school year, I had the opportunity to take a summer internship in the software engineering department at a company called 6 Degrees Health. Following the internship, I transferred to Oregon State University and moved to Corvallis to live just off campus. I had a great time and learned a lot while taking classes on campus, but unfortunately, the world went into lockdown for COVID in the middle of the spring term, forcing me to pivot. For various pandemic-related reasons, I went to work full-time for 6 Degrees Health, the company I had interned with. I completed a few courses sporadically over the next few years through e-campus but had to focus mainly on my job, and it looked like it would take me quite a while to graduate. Gradually, circumstances improved, and a few months ago I realized I was in as good a position as I would ever be to return to school, so I decided to focus on my degree full-time.

Healthcare billing is an interesting field with many challenging problems, but I am excited to get my degree so I can branch out into other areas. I am particularly interested in security and hope to eventually move into that industry.

I have been working for a startup called My Price Health for a little over a year now. My boss has been kind enough to allow me to continue working reduced hours while I complete my degree. In my job, I work on tools and systems for managing healthcare claims and eligibility data. I feel fortunate to do most of my work with Go and PostgreSQL, as I find both enjoyable to work with. I sometimes use Python or shell scripts for quick, ad-hoc tasks. Last winter, I switched my editor from Visual Studio Code to Emacs and have since developed an affinity for Emacs Lisp, which I now use whenever I can justify it.

There are many interesting projects for this course. Because of my interest in security, I am most drawn to the Website Security Research and Malware Analysis projects. Both sound like fantastic ways to gain valuable real-world experience in the field. The Website Security Research project, in particular, seems like it would be very practical. Having been involved in web development for a few years but knowing little about properly securing a website, it would be an excellent experience to build one specifically for researching vulnerabilities.

Categories
Uncategorized

Hello world!

Welcome to blogs.oregonstate.edu. This is your first post. Edit or delete it, then start blogging!