In this post, you’ll find how to reduce boilerplate on .NET IHost applications, enhance development speed, code readability and maintenance.
Hey, listen… Suppose you have a huge .NET solution with a bunch of Swagger projects or even pure MVC applications. If you look closer, you’ll realize that most of the code you wrote to initialize the applications is basically the same, it is known as boilerplate. Boilerplate code, while necessary, can lead to increased development time, reduced code maintainability, and potential errors. Fortunately, there are techniques to reduce boilerplate. In this post, I will show how to reduce boilerplate on .NET IHost applications, enhancing developer productivity and code quality.
This post will focus on dependency injection and extension methods however there are plenty of ways to reduce the boilerplate such as T4 templates or tools like AutoFixture (for testing), which may be explored in future posts.
Dependency Injection (DI)
Dependency Injection is a fundamental concept in modern software development and plays a crucial role in reducing boilerplate. By leveraging DI, you can inject services and components where needed, eliminating the need for explicit instantiation and reducing repetitive code. The .NET Core framework has a built-in DI container that makes this process really easy.
The next code shows a service class and how to use it on a controller.
You must register MyDearService, at Startup.cs or Program.cs, with services.AddScoped<MyDearService>() for the class to be available to be used in the controller.
public class MyDearService
{
// Service implementation
public async Task DoSomethingSpecial() {
// special stuff here
}
}
public class MyDearController : ControllerBase
{
private readonly MyDearService _myDearService;
public MyController(MyDearService myService)
{
_myDearService = myService;
}
[HttpGet]
public async Task<IActionResponse> MyNiceMethod() {
// Controller logic using MyDearService
await _myDearService.DoSomethingSpecial();
}
}
Extension Methods
To keep the Startup process clean and readable, encapsulate service registrations in extension methods. This not only reduces code size in the Startup process but also enhances readability and organization.
Example:
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddBootstrapServices(this IServiceCollection services)
{
services.AddScoped<MyDearService>();
// You can add many services as you need
return services;
}
}
// Then you can call it in Startup.cs (if ufing .NET prior to v6)
public void ConfigureServices(IServiceCollection services)
{
services.AddBootstrapServices();
// Other configurations
}
// Or call it in the Program.cs (if ufing .NET after v6)
services.AddBootstrapServices();
Practical Example
As proposed at the beginning of this post, imagine a solution with many projects, each one being a swagger API. Now instead of configuring each one individually, let’s use a base project called Commons. The Commons project will contain all the jazz necessary to configure and boot the application.
Solution with two swagger APIs and a shared Commons project
The Commons project has a Boot class, with the needed code to run the application and auxiliary extension classes with methods to register services and configure the pipeline.
Of course, you’ll need to install the Swashbuckle package to use swagger-related methods such as AddSwaggerGen and UseSwaggerUI.
To install the package use the Visual Studio Nuget manager or run the following command in the Commons project folder:
dotnet add package Swashbuckle.AspNetCore
ServiceExtensions class
This extension class holds the code to register all the necessary services. As this is a simple example, I’m only registering the swagger-related services but it could also have some other services like database and remote services like complementary REST services.
public static class ServiceExtensions
{
public static IServiceCollection RegisterSwaggerServices(this IServiceCollection services)
{
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
services.AddEndpointsApiExplorer();
services.AddSwaggerGen();
return services;
}
}
WebApplicationExtensions class
Here we should create all the methods needed to configure pipeline. Again, I’m only configuring swagger but one could add methods to configure and extend the pipeline to read request headers for instance.
public static class WebApplicationExtensions
{
public static WebApplication ConfigureSwaggerPipeline(this WebApplication webApp)
{
// Configure the HTTP request pipeline.
if (webApp.Environment.IsDevelopment())
{
webApp.UseSwagger();
webApp.UseSwaggerUI();
}
return webApp;
}
}
Boot class
This class has a single method to run the main application and call the extension methods builder.Services.RegisterSwaggerServices() and app.ConfigureSwaggerPipeline()
public static class Boot
{
public static void Run(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.RegisterSwaggerServices();
var app = builder.Build();
app.ConfigureSwaggerPipeline();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
}
Program class
To run the SimpleApi1 and SimpleApi2 programs we have to write a single line of code and call the static method Run from the Boot class. Now we can see great improvement in speed and code reuse.
Boot.Run(args);
The programmer has to make changes only in the Commons project when a new service is needed by the APIs or when some adjustments must be made.
Conclusion
In the ever-evolving landscape of .NET development, reducing boilerplate code is crucial for clean, scalable and maintainable applications. Dependency Injection and simple Extension Methods are effective strategies to streamline .NET IHosted applications. By implementing these simple techniques, developers can focus more on business logic and innovation, improving the overall code quality and development speed.
Diagnosing and fixing Faulty Electronics will show how to diagnose and repair electronics using parts you possibly have in your collection.
Hey listen…, electronic devices have become an integral part of our lives, providing or enhancing education, safety, medical care and entertainment on the go. However, like any device, it can break or develop faults over time. Although the new trend dictates throwing broken electronics in the trash, I will walk you through the process I used to diagnose a faulty multi-source audio player and what I did to fix it.
Identify the Problem
The first step in diagnosing and repairing any faulty electronic device is to understand and identify the problem. There are thousands of ways something can fail, for example, if your device has no power. That is, the device doesn’t turn on at all, there is no light, no sound no movement no nothing that indicates that it’s operating. It could be due to a dead battery or faulty charger, a faulty power button, or a problem with the internal circuitry.
I could write an entire post just to list some of the odd ways a device can fail but in this post, I will focus on a particular device with a particular problem. You should always think simply and if you cannot find the problem, you should think about more complicated things.
The Device
The device I worked on was a small and cheapy, battery-powered FM radio/audio player that could read audio files, a.k.a. mp3, from SDCards and USB flash drives and also had an auxiliary input jack, which is neat!
Front view. Main panel and speakersBack view with analog volume control power switch and audio jacks
I don’t know why but many cheap Chinese products have to have something odd or fake in them. This one had a fake speaker. One of the top speakers was fake and it was hard to tell which one was the fake one. I know now because I opened the device and saw it guts!
Top speakers. One is fake =]
Tools and Materials
Before you start diagnosing and repairing electronics, make sure you have the following tools and materials:
A clean workspace with good lighting
Screwdrivers (usually Phillips and sometimes Torx)
Multimeter (could be cheap as a flock but it must be a reliable one)
Soldering iron (I like the temperature-controllable ones but could be the simplest depending on the type of electronics)
Solder, of course (flux is good to have)
Oscilloscope (someday you’ll need a simple one)
Small plastic prying tools (I use cheap guitar picks)
Diagnose the problem
The problem with my little patient was that one of the two speakers (the real ones =]) suddenly stopped to play sounds. This scenario was always present, no matter if the audio source was FM radio, USB flash driver or the SDCard. Also, I tried to mess around with the buttons or the volume pot and the problem was still there.
Now is a good time to ask you to read the disclaimer page =].
Disassembly
I removed the back panel (that one with audio input and output jack) and discovered that there were two boards, one for the radio tuning, card reader, read buttons, drive the display, and all that jazz and another board with the audio amp. My attention was focused on the second board because I started to track the issue from de output (the speakers) to the input (probably a microcontroller).
First of all, I used the multimeter to measure the speakers not connected to the board. Both were good, with 4 ohms each. Then I measured spk 1 and spk 2, which are the speaker connectors, in reference to ground and I got around 2v on both! That was a surprise. I was expecting one of them to be shorted to ground. Before checking the voltages at spk 1 and spk 2 I was guessing that one of the chips went faulty, and I expected most of its pins with no voltage but that was not the case.
As the first observations were not conclusive, I searched for the integrated circuit datasheet. The chip marking was CM8600A, a 3-watt audio amplifier with a shutdown pin.
Chip pinout oriented like on the board
For this particular circuit, a datasheet is not really required because we can assume, with a basic understanding of audio amplifiers, that the chip must have at least one pin for input and another pin for output. In this way, one could follow the trace from the speaker connector to the chip, maybe expecting some passive component in between, and find the output pin.
Example circuit from the datasheet
The pinout figure and this example circuit, both extracted from the datasheet, show what we’ve got at the board.
After some more time probing around with the multimeter, I noticed that pin 4 of one of the chips was practically stable at 2v while the same pin on the other chip was oscillating a bit. Besides that, both chips seemed to be good.
Oscilloscope Probing
At this point, I was just guessing the faulty IC again, based on a little difference between the reading on pin 4. So, I decided to use the oscilloscope and probe the input and output pins. As expected, I got some messy waveforms because I was playing some random music.
To get a better idea of the waveforms, I used ffmpeg to create a stereo mp3 file with a particular tone frequency on each channel. For the left channel, I chose 550Hz and for the right channel 440Hz.
I’m using Linux and I can use ffmpeg it from a simple terminal emulator. If you are using Windows (without the Linux subsystem), I’m really sorry for you.
I loaded the generated mp3 file on an SDCard, just because I could, and started to probe again. This time I got a clear view of the problem. One of the chips, the one with the quiet pin 4, was dead. The input signal was good but there was no output. Moreover, I was able to find out that the volume control was not working properly!
Here are some pictures of the waveforms. I do not have the waveform of the dead chip because it was a flat line around the 2v.
Left channel probing before the volume control
This is the waveform of the left channel, probing the pin marked as “probe point 2” at the bottom left of the audio amp board.
Right channel probing before the volume control
This is the waveform of the right channel, probing the pin marked as “probe point 1” at the bottom left of the audio amp board.
Right channel probing after the volume control
This is the waveform of the right channel, probing the pin marked as “probe point 3” after the input capacitor. There was a little noise but I couldn’t hear it from the speaker.
Solution
The simplest solution to this kind of problem is to replace the faulty component. Unfortunately, the local electronic component supplier did not have this chip or a possible replacement. Also, I would need two of these chips because this device had a twin brother with the same problem. So I decided to transplant the functional chip to the brother and for this guy, I chose a more invasive procedure. I built an extension board with another audio amplifier.
Extension audio amp board – Top view
I used a DIP dual power amp, the TDA2822M that I had in my parts stash. It’s a good choice for this kind of project because is a low-supply voltage chip, it can operate at voltages down to 1.8v, ideal for battery-powered devices like this one.
Example of circuit application extracted from the TDA2822M datasheet
I used this example circuit provided by the TDA2822M datasheet for the extension board. Of course, I changed some passive components like the output capacitors and input resistors to fit my needs (all empirically =]). Also, I had to remove a pair of resistors (output) and change a pair of capacitors (input) from the original board.
Extension audio amp board – Bottom view
That was a pretty small perfboard to work on. The soldering was made with a pair of tweezers and a fine soldering iron tip. Fortunately, all went well and the amp was working nicely.
Extension audio amp board – Wiring to the main amp board
Is worth mentioning that the wiring should be as small as it could be to avoid interference, particularly at the input lines.
I built the same circuit on a small breadboard using long wires for the power supply, inputs and outputs. The breadboarded circuit tricked me for a while because it was extremely noisy with a lot of hum, I even thought the chip was defective. A decoupling capacitor is mandatory here!
Conclusion
Diagnosing and repairing any faulty electronics can be rewarding. Not only by resurrecting a piece of dead equipment and reducing e-waste but also because we can learn a bunch of new stuff. By identifying the problem, gathering the necessary tools, and finding suitable replacement parts or adapting them as needed, you can bring devices back to life.
Warning note here: Always exercise caution and prioritize safety, especially when working with electronics. If you don’t have the necessary skills yet, go to a repair shop to ensure a successful repair.
Learn step-by-step in this post how to create and apply themes to your Java Swing applications without using third-party libraries.
Stay awhile and listen… Java Swing is a robust framework for creating cross-platform graphical user interfaces (GUIs). While it provides a native look and feel across different platforms, there are times when you might want to customize the appearance of your Swing application to match your brand or achieve a particular aesthetic. This is where theming Java swing applications comes into play. I will show how I themed a particular Java Swing application to give it a unique and personalized look.
The application I worked on I made back in 2002, maybe, when I was learning Java by myself and guess what, the code was a mess. It was intended to find Runewords for the game Diablo 2. A remastered version of Diablo 2 was released a couple of years ago (2021) and thus I “remastered” my old application to fit the game’s beauty.
The Basics
Before we dive into theming, it’s crucial to have a good understanding of how Java Swing works and how it prints components on screen. Swing uses a hierarchy of components, such as Frames, Panels, Layout Managers, Buttons, Labels, etc., to build the GUI. To theme a Swing application, you’ll need to work with various aspects like colors, background, fonts and borders to customize these components. Also could be necessary to create your own custom components at some point.
Look and Feel (L&F)
Swing applications can be themed using different Look and Feel libraries. Two popular ones are:
Metal: The default Swing L&F that provides a consistent look across different platforms.
Nimbus: A more modern and customizable L&F with support for theming.
You can choose the L&F that suits your application’s style and requirements. More of that can be found here.
I created my custom components to match Diablo 2 look and feel, so I did not use any of these libraries.
The Original Application
I built this application to find a valid Runeword with runes the player has in its inventory. It has a filter panel with selectable runes (checkboxes) and a table showing results, if any, ordered by match count. That is, if the player has checked RuneA, RuneB and RuneC at the filter panel and a valid Runeword is “RuneC RuneA” the whole combination will appear first.
The original look and feel (running on a 2023 Java VM)
Although simple, this was a neat application back then. There weren’t few websites with this kind of information and even if the information was there you’d have to search the valid runewords filtering by yourself.
New Features
Some new features that I included in this update:
Item type filter: a panel with item types to be selected and filtered;
Status bar: a bottom panel with information;
Match indication: selected runes and items will change color to green when matched and red when not matched;
Auto sizing to columns: the column adapts the size to contain text;
JSON database: database changed from XML to JSON file;
Customize the Theme
Inspiration
I got some in-game screen captures to guide the theming. With ambient in mind, I started to search for textures and colors to match the game.
Diablo 2 Player’s stash and inventory
The new game modified the inventory panel and added some new menus.
Diablo 2 Game configurations
The main goals are to mimic the fonts, colors and components like buttons and checkboxes which have unique aesthetics. Elements like the background color, the dark atmosphere and the stone-like texture of the menu and its borders are also important but can be adapted.
Custom Components
We need some custom components to create a menu like the game.
Checkbox: a themed checkbox using the image from the game;
Fake transparent panel: a JPanel that simulates transparency;
Fake transparent label: a JLabel that simulates transparency;
Table header render: a table cell render just for rendering the headers;
Table cell render: a table cell render that handles the color and format of each cell;
Table model: a table model to hold the Runeword recipe;
Transparency
At first, I thought that setting the property opaque to false would turn a JPanel into a transparent panel, well, it’s not always true. A small but annoying glitch happens when the panel is over another panel that is transparent too and some shadows appear around components like labels and checkboxes when in focus or its state changes.
To fix that problem I used a base panel with a background image and every time I had a need for a “transparent” component over it, I just used the paintComponent method to copy and paste the area from the background image to the background of the component making it “transparent”, as I’ll show next.
Textured JPanel
This is a simple component that paints a picture as a background. I used this panel as a container for other elements.
This is a simple custom component that extends its functionalities from the JPanel component except for the paintComponent method which simulates the transparency effect.
The method paintComponent copy a rectangle of the same size as the component from the image, used as the background of the container panel, and paste as the background image of the checkbox component that is being drawn. Then, another rectangle filled with a translucid black color (alpha channel less than 1) is printed over the component bringing some darkness effect.
In this particular case, getX(), getY(), getX() + getWidth() and getY() + getHeight() are the dimensions for the source image and 0, 0, getWidth() and getHeight() are the dimensions for the component itself. This is kind of confusing because the source comes after the destination and may trick you somehow.
Transparent panel with border and title
Themed JLabel
This component has the same construction as the previous one but also prints the label text.
public class FakeTransparentLabel extends JComponent {
private final ResourceLoaderComponent resourceLoader = ResourceLoaderComponent.getInstance();
//text label
private String label;
private final FontMetrics fontMetrics;
private double labelLength;
public FakeTransparentLabel() {
super();
fontMetrics = getFontMetrics(resourceLoader.defaultFont);
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
if (this.label != null && !this.label.isEmpty()) {
var c = new Canvas();
var lm = fontMetrics.getStringBounds(label, c.getGraphics());
labelLength = lm.getWidth();
setPreferredSize(new Dimension((int) lm.getWidth(), fontMetrics.getHeight()));
}
}
@Override
protected void paintComponent(Graphics g) {
var g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawImage(
resourceLoader.defaultBackgroundTexture,
0,
0,
getWidth(),
getHeight(),
getX(),
getY(),
getX() + getWidth(),
getY() + getHeight(),
this);
g2.setColor(resourceLoader.colorShadow);
g2.fillRect(0, 0, getWidth(), getHeight());
g.setColor(getForeground());
g2.setFont(resourceLoader.defaultFont);
g2.drawString(label, getWidth() / 2 - (int)labelLength / 2, getHeight() / 2 + fontMetrics.getHeight() / 4);
}
}
Note that the method setLabel sets the text but also sets some metrics for drawing the text.
The method paintComponent is almost the same as the previous component except that it prints the string calling g2.drawString.
Transparent Label in red
Themed JCheckbox
I would say that after the fonts, colors and buttons, the checkbox is the most iconic interface item.
In order to make a checkbox component with the same characteristics I used gimp to copy the images that represent the checked and unchecked states and then created an empty class called MyCheckbox and extended it from the JComponent. This class is almost a mixture of the other two classes with an extra print for the image of the checkbox according to its checked/not checked state.
//width of the image
private final int SPRITE_W = 22;
//height of the image
private final int SPRITE_H = 21;
//little gap between the image and text
private final int LABEL_GAP = 5;
//the text label
private String label;
//whether is checked or not
private boolean selected;
This class is very common except for the following methods:
The method setLabel is used to calculate the final size of the checkbox label/text, using the defined font and paintComponent draw the component on the screen.
Transparent checkbox in yellowish color
The checkbox is glitchy in this example but it shows the transparency effect.
Themed JScrollBar
The scrollbar was divided into two parts. The first one is very simple, it is just a class extending JScrollBar and setting the UI. The second part is the UI itself.
public class MyScrollBar extends JScrollBar {
public MyScrollBar() {
setUI(new MyScrollBarUI());
}
public MyScrollBar(int orientation) {
this();
setOrientation(orientation);
}
}
The UI is more complex because the component is painted like the others I have shown here.
Here are the two most important pieces of code, a method to paint the thumb, called paintThumb and another to paint the thumb track or bar called paintTrack.
This class also implements the scrollbar buttons on a private class. There’s not much to see here except for the paintComponent method. Also, it’s worth mentioning that youshould always set the preferred size of a component otherwise it will not be painted.
There is just one image (the arrow pointing up) for the scroll buttons. Note that I applied a transformation to get a vertically flipped image (the arrow pointing down). If this scrollbar is used for horizontal scroll, SwingConstants.EAST and SwingConstants.WEST should be implemented by applying the correct transformation.
Besides that, the method is pretty much the same as the other classes.
Here is the paintComponent method for the scroll buttons.
Custom theming in Java Swing applications can significantly enhance their visual appeal and user experience. By working an appropriate Look and Feel, and messing around with colors, fonts, background and borders, you can create a unique GUI that aligns with the application’s desired aesthetics.