I'm a full-stack web developer, and this is my blog. Please connect with me on LinkedIn or visit my Github for more! Also, you may be interested in learning more about me.

Projects

  • An Intro to vavr's Either

    A pair of hands, one holding an apple, and another holding an orange. Either an orange or an apple would be delicious.

    Either is an incredibly useful tool in a Java programmer’s handbook, one that brings functional programming control to Java.

    If that didn’t make sense, I get it. Either is much easier to use, to me, than to explain.

    What Either does

    An Either is used when you want to return one of two types, typically a failure or a success. If an operation succeeds, we don’t really see any benefit of using Either. But if it fails, instead of throwing an exception and catching it, we can transform all our exceptions into a predictable failure class, which reduces boilerplate code.

    Here is a wonderful example from Yuri Mednikov on Medium:

    From a technical point of view, either is a container, that can hold two values — one for successful result and one for failed result. Imagine, that you write a code, that deals with file reading — you use a file service abstraction, that your colleague wrote for you. You don’t need to know how it works, you just call a method, that returns a content of the file. Yet, you know, that it may throw an exception, if file does not exist. Take a look on the following code snippet:

    FileReadService service = new FileReadService();  
    try {  
        String content = service.readFile("no-such-file.txt");  
        return content;  
    } catch (BadFilenameException ex){  
       System.out.println("No file found");  
        return readFromCache();  
    

    Imagine, that in future, the technical design will require the FileReadService to determine also other error cases. The number of catch clauses with increase… With Either type you can refactor this code as following:

    FileReadService service = new FileReadService();  
    String content = service.readFileSafely("no-such-file.txt").getOrElse(readFromCache());
    

    This style helps you not only to eliminate try-catch blocks, but also to specify a single entry point for all errors to make them to recover from a cache.

    The full article is a pretty good read, check it out.

    Getting fancier

    Once you’ve gotten the hang of basic Either usage, know that the real power of Either comes from chaining results. With the map() method we can transform an Either.right (which is by convention the happy-path case) any way we choose, and with mapLeft() we can transform an Either.left (by convention the error path case) in the same way.

    Imagine we have a service that queries for a row in a database and maps it to a database object. Then, since we don’t want our db models to leak into the rest of our service, we convert it to a service-level DTO. Without Either, it might look something like this:

    public MyDto findById(int id){
        try {
            MyDbModel result = repo.getById(id);
            if (result !=null){
                return mapToMyDto(result);
            }
        return null; //which will likely cause an error upstream
        } catch (JdbiException e){
        throw e; //or return null, which will cause another error upstream
        }
    }
    

    Pretty simple, but let’s walk through it.

    The code asks our repo class to find something by id. If it’s found, we’ll assume it’s mapped to our MyDbModel class. If the result is null, we have a problem. Similarly, if the database throws any errors, all we can do is try to catch them.

    With Either, our code can look like this:

    public Either<Problem,MyDto> findById(int id){
    return repo.getById(id).map(this::mapToMyDto);
    }
    

    It’s not just 10 fewer lines of code to write, it’s also, I would argue, easier to read. BTW, in this case Problem is a custom pojo that has a type, a message, and of course anything else we would like to add.

    In this example, we are also assuming that the repo method also returns an Either. If it’s a left, it is returned up the call stack until something determines what to do with it. If it’s a right, the model is transformed into a MyDto using the same mapper class.

    My current favorite Either method: sequence

    One very cool method that comes with Either, and one that I find myself using more lately, is sequence, which transforms a list of Eithers into an Either of lists. If that sounds confusing, imagine this example:

    public Either<Problem,<List<String>>> createStrings(List<String> inputs){
    

    Actually, wait, interruption time - I don’t know what this contrived example is supposed to do either. Let’s pretend we’re transforming these strings in a way that is possible to throw an error, but the transform method catches all errors and transforms them into Problems (our custom, predictable Either.left.). That would look like this:

    public Either<Problem,<List<String>>> createStrings(List<String> inputs){
        List<Either<Problem,String> results = List.of();
        for (String myString: inputs){
            results.add(performRiskyOperation(myString));
        }
    

    At this point we have performed some operation on every string in our list of strings, and added each result to a list to hold the results. Because performRiskyOperation returns an Either<Problem,String>, each item in the list is either a Problem or a string. In other words, if we were to inspect our list, it might look like this:

    results.get(0); //Left(Problem.UnsupportedOperation)
    results.get(1); //Right("hello");
    results.get(2); //Right("world");
    results.get(3); //Left(Problem.Null)
    

    But what we really want is all the strings, if the operation succeeded each time, or an error, if it didn’t. That’s where sequence and its cousin sequenceRight comes in:

    public Either<Problem,<List<String>>> createStrings(List<String> inputs){
        List<Either<Problem,String> results = List.of();
        for (String myString: inputs){
            results.add(performRiskyOperation(myString));
        }
        return Either.sequenceRight(results).toJavaList();
    }
    

    That one-liner turns the list of Eithers into one Either, which contains either a Problem, or the full, happy-path result (the list of strings). (toJavaList() is needed if you want to turn the Seq object, which is list-like but not a list, into a regular ol’ list.) sequenceRight will return a single Problem (the first one it encounters) or the full list; regular old sequence will return a list of Problems or the full list of strings. The cost is, well, the pretty ugly method signature of createStrings, but when you are working with lists and Either, it is a small price to pay.

    There are many other methods available within Either, and I hope you’ll read the docs on them here.

  • How to set up a backend FastAPI server on nginx (or: I am bad at devops)

    I’m setting up a new backend server for a silly side project I’m working on, and every time I do this I forget all the steps I need to follow.

    These steps are for a FastAPI server, served through nginx running on a Unix box (an Amazon EC2 instance running Ubuntu). My wonderful husband set up the nginx server over a decade ago. I’m just a tenant (hopefully a quiet tenant who is getting their security deposit back). Therefore, some of these instructions might also only work on 10-year-old systems with slightly idiosyncratic setups, but I think most of the steps are the same for most servers.

    Step 0: Build your FastAPI server

    This blog post doesn’t include how to do that. There are great docs on the project homepage, though. I had 0 experience with FastAPI a week ago and I have a working API today, so the docs must be great.

    Step 1: Buy a domain

    I used Cloudflare.

    Step 2: Point the domain to existing host

    What is my IP? IDK. I have other domains proxied by Cloudflare and they all point to the same place, so…that’s my IP. (I think the real answer is, look in the AWS console.) I setup an A record for the root domain (.mydomain.com) pointing to Github Pages and for my API (api.mydomain.com) pointing to my server’s IP.

    Step 3: Set up a basic ngnix config listening on port 80.

    To do this, we SSH into the server and add a config to /etc/nginx/sites-available/mysite.

    server {
    
     root /path/to/site/content;
     index index.html index.htm;
    
     server_name yourdomain.com;
    
     location / {
      # First attempt to serve request as file, then
      # as directory, then fall back to displaying a 404.
      try_files $uri $uri/ =404;
     }
     listen 80;
    }
    

    Read on →

  • Some Basic Rake Tasks for Jekyll Users

    An image of a zen sand garden being raked.

    I recently tweaked a few of the (very basic) rake tasks I’m using to keep this blog going. Ruby isn’t my thing, but writing these was interesting and I figured I’d share in case they are useful to anyone else.

    Wait, back up. What’s a rake task?

    Rake is a task runner in Ruby. Jekyll, which powers this blog, is written in Ruby. Similar to how a JS-based project might have scripts in package.json that allow a developer to run tests or start a server, rake allows devs to define custom tasks and then run them, using the syntax rake taskname. In my case, I wanted a task that would create a new draft based on a template, and a task that would automate deployment of the blog, to prevent any mistakes from making it into prod. (I recently erased my site by rsyncing the wrong directory to my server. I got it back a minute later, but I’m tired of doing that.)

    Ok, I’m sold. How do I write a rake task?

    I created a file in my site’s root directory called rakefile that holds the tasks. Then I define my tasks in Ruby. I had to google a lot of syntax for these very basic tasks – Ruby is not a language I know!

    desc "Create draft with template."
    
    task :newdraft do
      puts "new draft name: "
      my_file = STDIN.gets.chomp
      source_file = "path/to/site/root/folder/template.md"
      destination_file = "path/to/site/root/folder/_drafts/#{my_file}.md"
      unless File.exist?(destination_file)
        FileUtils.cp(source_file,destination_file)
        puts destination_file
      end
      cmd = "code #{destination_file}"
      system(cmd)
    end
    

    This defines a task that takes input from the user (me), and creates a new Markdown file from copying a basic template with some default front-matter defined, then opens it in VSCode. Notice I have basically no input sanitization here, and things like the default IDE (VSCode) are hardcoded. Change to suit your needs.

    The other thing you’ll notice is that the task has a description. This, it turns out, is required for the task to be discoverable by Ruby, so don’t leave it out!

    The second task is even simpler:

    desc "Build and deploy."
    task :deploy do
        system("/path/to/deploy/script.sh")
    end
    

    The deploy script is a simple bash script that changes to the site’s root directory, runs the jekyll build command, then rsyncs the _site folder to another folder on my computer, which is set up with Syncthing to copy new files to the remote web server. (This is not a typical build pipeline and I am thankful to be in a two-nerd household.)

    One might ask, why have a rake task if all it does is execute a shell script? The cool thing about rake tasks is they can be executed from anywhere in the directory tree at the level of the rakefile or below. As I understand it, rake will start in its current directory and then keep going upward until it finds a rakefile with a matching task name.

    This is why ‘real’ Ruby projects usually namespace their tasks, because this behavior in a big project could lead to issues. In my tiny project, though, it’s exactly what I want. Now, I can do rake deploy from anywhere within my site structure.

    Yes, I could also just run /the/full/path/to/deploy.sh from anywhere, but that involves more typing.

    That got me thinking, too – to start the Jekyll local server, I type bundle exec jekyll serve --drafts. This can be shortened to bundle exec jekyll s -D, and if I use history search it’s really not that bad to retrieve this command, but could I make this more efficent?

    With a rake task that looks like this:

    task :start, :withDrafts do |t, args| 
      trap('SIGINT') { puts "\nI quit."; exit }
      args.with_defaults(:withDrafts=>"false")
      puts("Running the server with drafts #{args[:withDrafts]? 'on': 'off'}")
      system '/path/to/start/file/start.sh', args[:withDrafts]
    end
    

    and a bash script that looks like this:

    #! /bin/bash
    
    SITE_ROOT_DIR="/full/path/to/my/site/root"
    WITH_DRAFTS=$1
    if [ $WITH_DRAFTS = 'true' ]; then
        cd $SITE_ROOT_DIR && bundle exec jekyll serve --drafts
    else
        cd $SITE_ROOT_DIR && bundle exec jekyll serve
    fi
    

    I can start a rake task that starts the server and waits until I ctrl-c to end the task. There are two somewhat interesting bits in the Ruby code: trap works the same as a bash trap, in that it listens for the ctrl-c signal and then executes the code in the function. This is just to make the exit look cleaner, the task works fine without it.

    And adding the :withDrafts parameter to the task, with a default set of false, allows me to pass true or false into the shell script. This syntax is pretty bonkers to me as a non-Ruby user but it seems to work fine.

    Note that for both of the tasks that run shell scripts, chmod +x script.sh is required to make Ruby able to run these as executables.

    This was a fun exercise. I have now written nearly 900 words on this topic, plus the testing and writing of the rake file itself, which means I have not yet saved myself any time with these new commands. But maybe a hundred or so blog posts later I’ll be singing a different tune. :)

  • What I Learned From Reviewing Hundreds of Conference Session Proposals

    A photo of someone grading papers. I did not actually give anyone an A+. Nor did I get the chance to write “see me”.

    Since last fall, I’ve been pitching (and giving!) talks at tech meetups and conferences. So far it’s been an excellent way to hone ideas, meet new people, and learn more about the things I thought I knew. (Nothing like the stress of having to tell people what you know about something to make you really study up!)

    This month, I marked an additional milestone: I was given the opportunity to be a conference session reviewer. I read hundreds of pitches over three categories for an upcoming conference, and what I learned about what makes a good session pitch both surprised me and didn’t.

    1. Titles REALLY matter. I’m a sucker for a pun or just a clever title. A boring title, on the other hand, can prejudice reviewers against otherwise great content!

      But a title that is clearly just pasted on also doesn’t work for me. I know there are people who decide up front that their talk is going to be, IDK, Avengers themed, and so they come up with a title that references the Avengers and then try to shoehorn their talk into the theme. Maybe some people are into that, but it’s not my thing.

    2. There’s a sweet spot for submission length. Maybe about 300 words, including a bunch of bullet points? I saw presentation pitches that were one or two sentences long, and I saw presentation pitches that were so long they caused a major vertical scroll on an otherwise pretty compact review page. Too much information can actually be a negative.

    3. Please, run spellcheck before you submit. I tried not to deduct points for submissions that contained spelling errors, grammatical mistakes and misplaced punctuation, because certainly people present differently than they speak, but it’s a pretty easy thing to fix and doesn’t reflect well.

    4. Tailor your presentation to the venue! Many conference submission platforms let you store reusable talks. This is great and it can save you a ton of time to start from a non-blank page. But you shouldn’t just hit submit blindly. After copying the talk to your submission, make sure that it’s a fit for the specific RFC.

      • Did you submit a day-long workshop for a conference only accepting 30-minute slots?
      • Did you propose a frontend talk for a conference focusing on backend?

      These examples are perhaps obvious, but there are less obvious ways your content might not be a fit (or could be a more obvious fit with some tweaking).

      Let’s say you want to give a talk on hidden features in your favorite IDE. If the conference is Javascript focused, the examples you give in your bullet points should call out features that work with Javascript. If the conference is dev tooling focused, maybe you have examples that span languages (and you explicitly point out that your talk is language-agnostic).

      These are small tweaks that shouldn’t take a long time when you’re putting together your proposal, but make it obvious to reviewers that you’ve thought about why your talk is a fit for this specific conference.

      Another example: if the conference is language-agnostic, you need to sell us on why your talk on a specific framework is relevant now. But if you’re pitching a talk on React to React Conf, you probably don’t need to tell us why we should be using React.

    5. A technical talk proposal doesn’t need to get so far into the nitty gritty at the proposal phase. The best ones I saw simply included the what (a language, framework or idea), the why (this language/framework/idea is more popular this year because of X), and a handful of takeaways, usually in bullet point form. Again, 300 words felt like the sweet spot.

    6. It’s really difficult (I think) to pitch an advanced language-specific talk to a generalist conference! But if you do, you need to explain why people should attend your talk. Forget the conference attendees – the people reviewing your pitch might not be experts in the thing you’re pitching, so to even get accepted, you might need to include enough background information to get your reviewers up to speed!

    7. I saw a handful of framings that kept popping up, some better than others.

    • Here’s how to get started with Thing. This can work, if you explain why attendees should want to get started with Thing.

    • 7 mistakes I made trying to do Thing. Numbers in a title, as journalists will tell you, are always good. It doesn’t have to be 7. The mistakes help though.

    • Some Thing you thought was bad is actually good, and here’s why. This framing is catnip for me. I always want to hear how I’ve been thinking about things wrong.

    • What’s new with Thing You Already Know About since you last learned it. I saw a handful of talks with this angle at Frontrunners this winter and I’m so into it. I always learn something.

    • I built A Thing and intentionally limited myself to doing it the hardest/most oldschool way possible, to prove it can be done/demonstrate the benefits of some technology. This can be interesting but there’s only room for a few talks like this at a conference (IMO).

    • If you know Thing 1, here’s how to apply that knowledge to Thing 2. This is really hard to do at a generalist conference, because it presumes knowledge of Thing 1, but could work well at a conference that specializes in one language or framework.

    This was such a rewarding experience getting to “peek behind the curtain” at what goes on during proposal selection, and I’m so glad I did it. Also, stay tuned for more exciting conference news from me soon :)

  • Partially Mocking a Class in Java

    Nelson from the Simpsons pointing and saying "HA-HA!". This is an example of complete mocking, but not the kind of mocking this post discusses.

    I love writing unit tests. i know this is an unpopular opinion but I just really like it. I love thinking of edge cases that could break code and then coming up with exactly how to create a test that will prevent that.

    However, mocking everything stinks. Yes, we should be using in-memory fakes instead of mocks as much as possible, and I’ve been working toward this, but it is not realistic to make everything a fake.

    My very smart coworker just alerted me to this method built into Mockito’s when method, which is used for controlling the behavior of mocks. If you want to stop reading now, just read the next two lines, and then you can go:

    when(thing.method()).thenCallRealMethod()

    This bypasses any mock behavior and goes back to the real class’s implementation. Handy!

    For absolutely more details than you need, here’s an example:

    class MyClass(){
     public int myMethod(){
      return 1;
     }
    }
    
    class SomeTestClass(){
     public MyClass myClass = mock(MyClass.class);
    
     int result = myClass.myMethod();
    
     assertEquals(1, result);
    }
    

    This contrived example will fail, because we haven’t explicitly declared the behavior of myMethod. (It will return null instead.)

    So what I would have done yesterday would look like this:

    class MyClass(){
     public int myMethod(){
      return 1;
     }
    }
    
    class SomeTestClass(){
     public MyClass myClass = mock(MyClass.class);
     when(myClass.myMethod()).thenReturn(1);
     int result = myClass.myMethod();
    
     assertEquals(1, result);
    }
    

    This will work (ignore the part where this test is a tautology!), but if your method under test has a lot of external calls that you’re mocking out, this can get messy. That’s where .thenCallRealMethod() comes in. If you had:

    class MyClass(){
     public int myMethod(){
      return 1;
     }
     public int someOtherMethod(){
      return 3;
     }
    }
    
    class SomeTestClass(){
     public MyClass myClass = mock(MyClass.class);
     when(myClass.myMethod()).thenReturn(2);
     when(myClass.someOtherMethod()).thenCallRealMethod();
     int result = myClass.myMethod();
     int result2 = myClass.SomeOtherMethod();
    
     assertEquals(2, result); //true because we have mocked the behavior of this method
     assertEquals(3, result2); //true because the real method returns 3
    }
    

    Like I said: Handy!

> > >Blog archive