+ Although I don't generally write much, sometimes I'll find something interesting, or something that I notice a significant number of people could benefit from reading about. In that case, it'll most likely end up on this page as an article.
+
+
+
+
+
+
+
diff --git a/articles/beginner-guide-to-apache-lucene.html b/articles/beginner-guide-to-apache-lucene.html
new file mode 100644
index 0000000..75a57b6
--- /dev/null
+++ b/articles/beginner-guide-to-apache-lucene.html
@@ -0,0 +1,271 @@
+
+
+
+
+ A Beginner's Guide to Searching With Lucene
+
+
+
+
+
+
+
+
+
+
+
A Beginner's Guide to Searching With Lucene
+
+ Written on , by Andrew Lalis.
+
+
+
+
+ Nowadays, if you want to build the next fancy new web app, chances are pretty good that you'll need a search bar in it, and for that, you've probably heard of ElasticSearch, or some other fancy, all-in-one solution. However, in this article, I'd like to try and convince you that you don't need any of that, and instead, you can brew up your own homemade search feature using Apache Lucene.
+
+
+ Hopefully you'll be surprised by how easy it is.
+
+
+
+
The Use Case
+
+ Before we dive into the code, it's important to make sure that you actually need an indexing and searching tool that goes beyond simple SQL queries.
+
+
+ If you can answer "yes" to any of these questions, then continue right along:
+
+
+
I want to search over multiple different types of entities.
+
I want to prioritize matching certain fields from entities over other fields. (For example, a user's name should be more important than their nickname.)
+
I'm okay with search results being eventually consistent (that is, it might take a moment for new data to appear in results).
+
I want to search for results that match a wildcard search. (For example, "find all animals whose name matches tig*.
+
+
+
+
Indexing and Searching Basics
+
+ No matter what searching solution you end up choosing, they all generally follow the same approach:
+
+
+
Ingest data and produce an index.
+
Search for data quickly using the index.
+
+
+ In most situations, ingesting data roughly translates to scraping content from a database or message queue, or even CSV content. The contents of each entity are analyzed and the important bits are extracted and stored in a compressed format that's optimized for high-speed searching. The exact implementation depends on what sort of solution you choose, but a lot of databases use a sort of red-black tree structure.
+
+
+ Searching over your index involves parsing a user's query (and sanitizing it, if necessary), and then constructing a well-formed query that's accepted by your searching solution, possibly with different weights or criteria applied to different fields.
+
+
+ This is no different for Lucene, and in this guide, we'll go through how to create an index and search through it.
+
+
+
+
+
+
+
Setting Up a New Project
+
+ In this guide, I'll be creating a small Java program for searching over a huge set of airports which is available for free here: https://ourairports.com/data/. The full source code for this project is available on GitHub, if you'd like to take a look.
+
+
+ I'll be using Maven as the build tool of choice, but feel free to use whatever you'd like.
+
+
+ We start by creating a new project, and add the apache-lucene dependency, and the Apache Commons CSV library for parsing the CSV dataset.
+
+
+
+
+
Parsing the Data
+
+ First of all, we need to parse the CSV data into a programming construct that we can use elsewhere in our code. In this case, I've defined the Airport record like so:
+
+
+
+ And a simple AirportParser class that just reads in a CSV file and returns a List<Airport> (Check the source code to see how I did that).
+
+
+ Now that we've got our list of entities, we can build an index from them.
+
+
+
+
+
Indexing
+
+ In order to efficiently search over a massive set of data, we need to prepare a special set of index files that Lucene can read during searches. To do that, we need to create a new directory for the index to live in, construct a new IndexWriter, and create a Document for each airport we're indexing.
+
+
+
+ An important takeaway here is the construction of the Document. There are a variety of fields that you could add to your document, which have different effects on the search.
+
+
+
StoredFields are fields that just store plain data, but can't be searched on. In the above code, we store the id and wikipedia link, since they might be nice to have when fetching results, but nobody is going to want to search for airports by our internal id.
+
TextFields are fields that allow for a full-text search of its value. This is generally the most popular "searchable" field type. It also allows us to specify whether or not we want to store its value, just like with a StoredField. In our case, we do want to store all our fields.
+
+
+ For more information about the types of fields that you can use, check the Lucene documentation. It's very well-written.
+
+
+ Also important to note is that once a document is added, it's staying in the index until either the index is removed or overwritten, or the document is deleted through another IndexWriter method. I'd suggest reading the documentation if you'd like to learn more about how to dynamically update a living index that grows with your data. But for 95% of use cases, regenerating the search index occasionally is just fine.
+
+
+
+
+
Searching
+
+ Now that we've built an index from our dataset, we can search over it to find the most relevant results for a user's query.
+
+
+ The following code might look a bit daunting, but I've added some comments to explain what's going on, and I'll walk you through the process below.
+
+
+
+
We check to make sure that the user's query is legitimate. If it's just empty or null, we can exit right away and return an empty result.
+
Since we want to make some fields have a greater effect than others, we prepare a mapping that specifies a weight for each field.
+
In Lucene, the Query object is passed to an index searcher to do the searching. But first, we need to build such a query. In our case, we want to match each term the user enters against any of the fields we've added a weight for. By using a BooleanQuery, we can construct this as a big OR clause, where each term is a wildcard query that's boosted by the weight of the field it applies to.
+
Finally, we open up a DirectoryReader on the index directory, create an IndexSearcher, and get our results. The searcher produces a TopDocs object that has a scoreDocs property containing the list of document ids that appear in the results. We can use the searcher to lookup the stored fields of each document in the result set, and in this case, we just fetch the name of the airport.
+
+
+ That's it! In my sample project, the whole Lucene implementation for indexing and searching, including imports and comments, is less than 150 lines of pure Java! It's so simple that it can just be tucked away into a single class.
+
+
+ Now, with your newfound knowledge, go forth and build advanced search features into your apps, and be content that you've built your solution from the ground up, without reinventing the wheel or getting roped into a complex cloud solution.
+
+
+
+
+ Back to Dev Discussions
+
+
+
+
+
diff --git a/articles/d-prospects-for-future.html b/articles/d-prospects-for-future.html
new file mode 100644
index 0000000..661b641
--- /dev/null
+++ b/articles/d-prospects-for-future.html
@@ -0,0 +1,139 @@
+
+
+
+
+ The D Programming Language: Does it have a future?
+
+
+
+
+
+
+
+
+
+
+
The D Programming Language: Does it have a future?
+
+ Written on , by Andrew Lalis.
+
+
+
+ If you've spent any time around me in programming forums or Discord channels, you might be aware of my somewhat
+ zealous nature regarding the D programming language and its potential to be the
+ next great language. In this article, I'd like to dive into the various reasons I have for taking such
+ a radical stance, and contrast those ideals with some harsh realities.
+
+
+
The Potential
+
+ Because it was designed many years after the advent of most of the main programming languages that form the
+ backbone of our software (C, C++, Java, Python, etc.), D has the benefit of 20/20 hindsight that it uses to
+ improve over some quite glaring flaws in earlier languages.
+
+
+ From our past, we've learned a few key things which contribute to great languages:
+
+
+
Expressiveness: it should be very easy to express complex structures and processes.
+
Abstraction: programmers should be able to create abstractions without significant extra cost.
+
Ease of use: it should be really easy for new programmers to get started, and for pros to do things quickly.
+
Performance: programs written in the language should be reasonably efficient and fast.
+
+
+ Of the other languages I've mentioned, each of those easily achieves a few of these requirements: C++
+ is expressive and allows efficient abstraction, and it's very fast. However, it's generally accepted that
+ the learning C++ is quite difficult. Again, Python can arguably meet the first three requirements, but fails
+ to provide satisfactory performance for many applications.
+
+
+ I think that D is a language which addresses all of these requirements in a modest, satisfactory approach.
+
+
+
D allows the same level of expressiveness as C++, while offering the convenience of Java when you don't want that.
+
Abstraction in D is as simple as in Java.
+
D is relatively easy to learn, because of its simple module structure and automatic memory management by default.
+
Because D compiles to machine code, it is inherently open to all sorts of optimizations from LLVM and GCC compiler backends, earning it very good performance that's faster than Java but just shy of C++ in most cases.
+
+
+
+
+ Of course, I could list all of the language features here which allow D to excel in each of the basic
+ requirements, but in short, it offers all of the power of a low-level systems language like C++, while at
+ the same time offering the convenience of high-level languages like automatic memory management, and
+ metaprogramming. So, I think that D is somewhat unique in that it gives programmers a freedom to choose
+ their own preferred style; it's a language accomplishes as much as a family of languages.
+
+
+
+
Why Isn't D Popular?
+
+ You'd think that all these benefits, developers would be flocking in droves to D. But clearly in the real
+ world, that's not the case. Why? This section outlines some of the reasons why the language
+ hasn't attained the same level of popularity as others.
+
+
Late to the Party
+
+ Despite their modern-day popularity, all of the major programming languages are several decades old: Java
+ was created in 1995, Python in 1991, C++ in 1985, and so on. D was first conceived in 2001, giving all of
+ these other languages years to build a loyal following. Additionally, the early version of D
+ was highly volatile and suffered from having two competing implementations of a standard library. In 2007,
+ D2 was released for the first time, marking the "stabilization" of D, and the language has essentially grown
+ from there. So we're dealing with a relatively immature language as of yet, which still needs to prove its
+ worthiness in various disciplines before it gains popularity.
+
+
Paradoxical Loneliness
+
+ One fatal issue which affects many software projects is this: the project receives little attention from new
+ users, so it is not promoted to new users. Therefore, the project yet again receives little attention from
+ its limited userbase, and so on... D is no exception. Other popular languages were quickly adopted by large
+ corporations: Java by Oracle, C++ by Microsoft, Python by Google, etc. Now we're in a situation where most
+ large employers will choose a "tried and true" programming language that's been used by other corporations,
+ and thus less popular languages stay in the shadows. Since D isn't so radically different than other
+ languages but instead offers smaller meaningful, incremental improvements, it's also not the most flashy
+ new language for individual developers to rave about in the free time.
+
+
A New Ecosystem
+
+ Stemming from the other reasons mentioned above, because D is relatively new, its software ecosystem is
+ still growing, and lacks some of the mature, standard libraries we've come to expect from a general-purpose
+ programming language: a standard async library, an HTTP client, a standard GUI framework, and the list goes
+ on. Over time, these problems are usually solved by the community, so I believe that D will emerge with a
+ robust library of modules that rivals the Java and C++ ecosystems.
+
+
+ Back to Dev Discussions
+
+
+
+
+
diff --git a/articles/dsh-easier-scripting-in-d.html b/articles/dsh-easier-scripting-in-d.html
new file mode 100644
index 0000000..976efbf
--- /dev/null
+++ b/articles/dsh-easier-scripting-in-d.html
@@ -0,0 +1,134 @@
+
+
+
+
+ DSH - Easier Scripting in D
+
+
+
+
+
+
+
+
+
+
+
DSH - Easier Scripting in D
+
+ Written on , by Andrew Lalis.
+
+
+
+
+ You're probably used to writing your automation scripts in a language like Bash, Powershell, Ruby, or Python. With DSH, it can be just as easy to write those scripts in D. I've designed DSH as a combination of a standalone programming library, and a set of tools to facilitate faster development and deployment. This article will discuss some of the basic use cases and how DSH works to make it easier to accomplish them.
+
+
+ In case you're interested, you can check out DSH on code.dlang.org or on GitHub.
+
+
+
+
Why write scripts in D?
+
+ While many people are used to scripting in languages that have been built over the years specifically for that use case, this introduces extra complexity into projects that are mainly built using some other language. In an ideal world, we'd use one single language to describe everything about our app, from the way it looks, to how we compile and distribute it. DSH is my attempt to make this a reality, at least for applications written in D. When developing D programs that require some auxiliary scripts, you don't have to make a cognitive jump to another language; just keep writing code in the environment you're most efficient in. This way, we reap the benefits of specializing in becoming an expert in a single language and its ecosystem.
+
+
+ If you're still not fully convinced, that's alright; read ahead and see if any of my examples can sway your opinion.
+
+
+
+
Writing Your Script
+
+ There are two main ways to write scripts using DSH:
+
+
+
+ Add a dub.sdl package descriptor to the top of your file, and an executable shebang. For example:
+
+ Executing these scripts involves compiling them first. dmd my_script.d /usr/include/dshs.d && ./my_script
+
+
+
+ Generally, the dynamic form is more useful for scripts you'd like to distribute to anyone, since they only require the user to have the D toolchain installed in order to run it. However, it is slower, since the script and all its dependencies must be compiled on-the-fly.
+
+
+ Alternatively, the static form is more useful for complex scripts that are best pre-compiled, or for when you don't want to use the dub package manager, just a D compiler.
+
+
+ Luckily for either of these solutions, DSH comes with a dshutil tool to help you get started. You can install it like so:
+
+ I won't go into all the features of dshutil here, since you can read the full documentation on GitHub, but in short, it provides shortcuts for creating boilerplate scripts, automatically compiling when changes are detected, and gives you access to the dshs.d single-file library for static scripts.
+
+
+
+
+
Helper Functions
+
+ While dshutil is a handy tool on its own, the real benefit of using DSH is its library of helper functions which are designed specifically for scripting tasks.
+
+
+
File Utilities
+
+ DSH offers quite a few helpful functions that reduce the verbosity of your IO operations. Below is a sampling of some of the most prominent functions.
+
+ In addition to the functions in D's std.process module, DSH provides some shortcuts for scripts to make it easy to manage processes.
+
+
+ import dsh;
+
+ void main() {
+ run("cat out.txt");
+ runOrQuit("git pull"); // exits the program if the process fails.
+ setEnv("MY_VAR", "TRUE");
+ print(getEnv("MY_VAR"));
+ }
+
+
+ Also included is a ProcessBuilder class with which you can use a fluent method interface to construct processes with custom input and output sources and environments.
+
+
+ Back to Dev Discussions
+
+
+
+
+
diff --git a/articles/java-swing-2d-game.html b/articles/java-swing-2d-game.html
new file mode 100644
index 0000000..a58c0a5
--- /dev/null
+++ b/articles/java-swing-2d-game.html
@@ -0,0 +1,252 @@
+
+
+
+
+ Java + Swing 2D Games
+
+
+
+
+
+
+
+
+
+
+
2D Game Development with Java and Swing
+
+ Written on , by Andrew Lalis.
+
+
+
+
+ Often times, new programmers will immediately jump into making graphical applications using their new-found skills, without getting a firm grasp of how to design something that doesn't require refactoring literally any time new functionality is required. Obviously, we can't just collectively tell all new programmers to just be patient; that will never work. So hopefully this article can serve as a guide to put you on the right track to developing 2D applications (games, most likely) using Java and Swing.
+
+ I will be referencing snippets of code that come from this repository, so check there if you want to read through all the code yourself.
+
+
+ Since this is quite a large guide, you can skip to a particular section if you want:
+
+ At first, it's super easy to make a new JFrame and start drawing on it, and you can add action listeners everywhere, whenever they're needed. If you ever plan on expanding beyond a simple 20-line drawing method however, you should organize your code using the Model-View-Controller pattern. For example, in my Before Asteroids sample game, I have split up my code into a few different packages.
+
+
+
control - Contains all my game's listeners for player interaction.
+
model - Contains all the code that makes up the core game model.
+
view - Contains all the code for rendering the game model.
+
physics - Some special physics code that is needed when updating the game model.
+
util - Extra utilities for things like file IO.
+
+
+ In most cases, it's especially useful to define a single class that represents your entire game's state; a so-called Game Model. This model would contain all the entities in your game that exist in the world, for example. Or in the case of something like a simple tic-tac-toe game, it would contain data about the status of each of the nine squares on the board.
+
+
+ Keep this design pattern in mind, and working on your project as it grows larger hopefully won't become as much of a headache anymore.
+
+
+
+
Setting up a Swing GUI
+
+ Making a Swing GUI usually consists of two basic components: the JFrame that acts as your application's window, and a JPanel that is used for actually drawing your model. Usually we start by defining our own frame to extend from the base JFrame, and set its properties in a constructor.
+
+
+
+ Inside the frame, there's a single GamePanel that we give a reference to the game model. This panel is responsible for rendering the model to the screen, and usually we can just define it as a child class of Swing's JPanel.
+
+
+
+
+
The Game Loop
+
+ First of all, this guide won't go too in-depth about the details of game loops in general, but focuses specifically on their implementation with Java/Swing. For more information, you can read this excellent article on the subject.
+
+
+ In Swing GUIs, your application is by-default multi-threaded, since Swing has its own thread for managing the user interface. In order to run our game and not interfere with Swing's own GUI processing, we should have our game update logic run in its own thread. The thread should periodically update the model, according to some defined frequency, and it should also trigger the rendering of frames of your game, once again according to some defined frequency. In the example below, we update physics 60 times per second, and render the model also 60 times per second, but these values can easily be changed due to how I've set up the math.
+
+
+
+ We can add our game updater thread to the end of our frame's constructor, so that when we initialize the game frame, the game loop begins.
+
+
+
+
+
Listeners and Control
+
+ Most often, you'll want something to happen when the player presses a key or clicks the mouse. To do this, you should create your own class which extends from KeyAdapter or MouseAdapter, depending on what you want to do.
+
+ You can also directly implement KeyListener and MouseListener at the same time, but this isn't as clean, and you have to implement every method declared in the interfaces, even if you aren't using them.
+
+
+ Let's take a look at a common case: doing something when a key is pressed. To do so, we override the KeyAdapter's keyPressed method like so:
+
+
+
+ Handling mouse events works almost the same way, but instead we check what button of the mouse was pressed.
+
+
+
+ Back to Dev Discussions
+
+
+
+
+
diff --git a/articles/spring-osiv-transactions.html b/articles/spring-osiv-transactions.html
new file mode 100644
index 0000000..0013752
--- /dev/null
+++ b/articles/spring-osiv-transactions.html
@@ -0,0 +1,81 @@
+
+
+
+
+ Spring's Open-Session-in-View & Transactions
+
+
+
+
+
+
+
+
+
+
+
Spring's Open-Session-in-View & Transactions
+
+ Written on , by Andrew Lalis.
+
+
+
+
+ If you're reading this article, there's a good chance you've already heard about Spring's controversial OpenSessionInViewFilter, which allows lazy loading of entity relations during the rendering of a web view. In case you haven't, I suggest reading this excellent article by Vlad Mihalcea which goes into much more detail on why one should avoid using the filter entirely.
+
+
+ This article will focus on the practical way to structure your application logic so that you can still take advantage of Hibernate's lazy loading, without using the OSIV anti-pattern.
+
+
+
+
Don't Send Entities to Your View
+
+ At first, many of the simple tutorials you'll read online will have you passing your entity models to Thymeleaf or JSP templates to render a web page for your application. This convenience is what leads developers to use OSIV in the first place, because they start fetching attributes of their entity which were not initially loaded. This is fine for the most simple "Hello World" starter projects, but as soon as you add any real complexity, this "convenience" breaks down into an unorganized mess, where it is not clear at a glance where data will be fetched from the database.
+
+
+ One solution, which beginners often turn to, is to simply eager-fetch all the attributes they'll need using a their data-access object (usually a repository with a custom JPQL query). This works well enough, and is often the preferred solution since it's about as optimized as you can get. The issue with this approach is that it's just not scalable to maintain a huge library of queries that are each tailor-made for a particular use case, and tends to sidestep Hibernate's powerful lazy-fetching features.
+
+
+
+ Eager-fetching the right attributes for an entity still leaves you with the issue of passing your actual entity object to the view for rendering, which means that an unsuspecting developer will eventually try to read a lazy-loaded attribute, which will throw a LazyInitializationException. The solution to that issue, is to not pass your entity to the view at all, but instead pass a data-transfer object (DTO) containing exactly the data that the view requires, and nothing more. And now, your service layer is responsible for producing this DTO, and it can take full advantage of Hibernate's lazy-loading functionality.
+
+
+
+
Transactions
+
+ The Spring framework allows you to annotate a service's method as @Transactional, which means that at runtime, when your method is called, a proxy method is wrapped around it which starts a transaction (and thus a Hibernate session to go with it) that persists for the duration of the method. Inside this method, you are free to fetch lazy-loaded attributes from an entity, without having to deal with LazyInitializationExceptions.
+
+
+
+ One caveat to be aware of is the fact that entity object should not be passed as arguments to a transactional method, since the Hibernate session that is dedicated to the transaction has no idea what that entity is, and thus can't fetch lazy attributes from it.
+
+
+ However, the flexibility of being able to use lazy-loaded attributes the easy way more than makes up for the strict encapsulation rules, and by structuring your project around service methods as black-box operations, you'll be able to build huge projects while keeping your sanity mostly intact.
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim feugiat tortor. Donec non gravida massa. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aliquam eleifend nunc placerat ante suscipit consequat. Nulla tempor pellentesque mollis. Nam malesuada risus urna, ac fermentum dui egestas sit amet. Ut vel tellus eros. Phasellus massa erat, dignissim ac arcu non, vestibulum rhoncus diam. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec pharetra pretium purus, et tempus elit tristique maximus. Donec imperdiet, enim et consequat pharetra, purus augue congue nulla, a hendrerit nulla est id augue. Aliquam erat volutpat. Fusce eu lorem purus.
+
+
+ Curabitur lobortis convallis nunc interdum mattis. Suspendisse tincidunt nec mi in elementum. Vestibulum eu sagittis felis, at bibendum odio. Quisque tortor mi, convallis ut nulla id, scelerisque scelerisque eros. Duis convallis enim lorem, sit amet congue ipsum eleifend et. Phasellus finibus elit nibh, nec sodales nisi vehicula quis. Quisque a elit nec turpis maximus posuere id ac turpis. Aliquam efficitur accumsan tortor, sit amet hendrerit eros faucibus eget. Mauris non est in lectus hendrerit varius pellentesque at ante. Morbi sit amet suscipit ligula, vitae condimentum quam. Etiam diam nunc, vehicula a fermentum nec, varius nec diam. Etiam elit tellus, mattis eu libero quis, faucibus varius est. Here is a link to Google.com.
+
+
+
+
+
+
Subsection
+
+ Praesent elementum quam in odio sodales, vel suscipit massa dignissim. Aenean id molestie lectus. Vestibulum eu magna scelerisque dui elementum molestie. Vestibulum vitae interdum felis. In rutrum turpis at posuere fermentum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Duis porta blandit blandit. Morbi ut vehicula metus, tristique ultrices justo. Vivamus ullamcorper convallis tempus. In et laoreet quam. Maecenas lobortis, enim ut tincidunt ultricies, dui mauris dictum magna, vel facilisis nunc nisi at ligula.
+