Add more geometry, like edge loops around the holes, to control the shading. This is the "traditional" way to do it, it works pretty well (and for some instances this is the best option). The negative is that it adds more geometry that you might not want.
Use the Edge split modifier. This is also a more "traditional" way, but can cause problems (and it adds more geometry). It breaks the mesh along certain corners (depending on angle)
Enable Auto Smooth (in mesh options) and tweak the angle. This is the best option (IMHO), but might need some help from additional geometry sometimes. This let's you define what angles should be considered "sharp" (and thus shaded as such), it also let's you mark edges as sharp (In Edit mode: Ctrl+E > Mark Sharp), so you can control the "smoothness". In this case, just enabling "Auto Smooth" should work fine, but you could also select the edges of the holes and mark them as sharp.
Windows 10 Pro - AMD Ryzen 7 2100X 8 core 3.70GHz - 32GB RAM - GeForce GTX 1080 8GB Octane Prime - Blender Plugin user