Junilu Lacar

+ Follow
since Feb 26, 2001
Junilu likes ...
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
Merit badge: grant badges
Forum Moderator
Junilu Lacar currently moderates these forums:
Cows and Likes
Total received
In last 30 days
Total given
Total received
Received in last 30 days
Total given
Given in last 30 days
Forums and Threads
Scavenger Hunt
expand Rancher Scavenger Hunt Green check
expand Ranch Hand Scavenger Hunt Green check
expand Greenhorn Scavenger Hunt

Recent posts by Junilu Lacar

Stephan van Hulst wrote:However, I'm definitely not a fan of the -Impl naming scheme. I prefer an implementation of the FooService interface to be named something like StandardFooService or DefaultFooService.

Yes, this is one case where hinting at the implementation of a class in its name is a valid exception to the general rule of names, "Choose names that express intent rather than implementation."

For example, with data related services, I might use "Jdbc" as a prefix for a JDBC implementation or "InMemory" to indicate that the implementation is, well, in memory.

I'm curious though, what alternative are you offering to those who are attached to the "Impl" suffix?

Say someone asks "If we don't use the 'impl' suffix, how can we tell that something is an implementation of an interface then?"

How would you answer that?

Lou Hamers wrote:
Just delete the interface! It's not rocket science adding one in later on in the rare situation that you find you need two implementations.

I might hesitate at deleting the interface, especially if it has already been published and there's a chance that it's used outside of the current code base. Also, the interface might make it easier to test with mocks or other kinds of test doubles. I would limit the scope of test-only implementations though. These are considerations for things that sit at integration boundaries, like DAOs and such. If something is fully contained in a module and only used internally, then I'd be more willing to consider deleting the interface.
I can't disagree with you. These are the (weak/lame) justifications I've run into:

1. That's our team convention (meaning, "Shut up")
2. We (were told / read / researched) that's a best practice (meaning, "Shut up")
3. Changing it now would mean we'd have to change it everywhere, and that's too much work (meaning, "Shut up")
4. ... blah blah blah (meaning, "Shut up")

If people would rather give you a justification for NOT changing, they're really just saying "Shut up". If I have any agency (which fortunately, I did), I just go ahead and make the switch. For me, doing what makes sense trumps consistency. If I don't have the agency, then I just suck it up.
Day 9 was interesting in terms of learning. Very satisfying, too.

After reading the problem, I knew I'd be writing a recursive solution. Sure enough, I got an initial one to work with the examples pretty quickly. But when I ran it against my puzzle data, I got the wrong answer. Too high, apparently. How nice. How the heck do I find which data is screwing with my program? Good thing I thought of a test that helped me find my bug. It was kind of subtle because I didn't think of the nuance until I saw it in the test.

Tip: Just because the sum of all elements is zero, it doesn't mean all elements are zero.

When I realized what the problem was, it was a quick fix to the lambda expression. Part 1 solved.

Part 2 was ridiculously easy to solve, given the way I had set up the semantics of the program. Check this out:

I spent more time writing the tests for it, but not a whole lot more. Done in less than ten minutes.

Then the challenge was to find a way to use tail recursion. Took me longer than it should have but I eventually got that, too. Tail-call recursion isn't the most intuitive thing for me. Need more practice.

Overall, I learned quite a few things with the Day 9 problem. I doubt I can get caught up before Christmas Eve though. Lots of ground to make up. Anyway, it already snowed last night where I am, so I guess most of the people doing AoC got the big snow-making machine in the sky back up and running again.
2 months ago
I'm way behind: only starting Day 8 on this 18th day of Advent. But I'm learning a lot and having fun with Kotlin again. I think Day 7 has been my best solution so far. The Part 1s are pretty easy but the Part 2s have turned out to be harder that I thought they would be at first. Part of it is that I'm trying to fit Part 2 solutions in with the Part 1 solutions as best I can. I'm always looking to extract and abstract. Interestingly, there's also quite a bit of inlining and combining. It's great practice, plus the problems are fun.
2 months ago
I just looked at Todd Ginsburg's Day 7 solution at https://github.com/tginsberg/advent-2023-kotlin/blob/main/src/main/kotlin/com/ginsberg/advent2023/Day07.kt and I think I finally came up with one that I like more than his, all bias aside.

Any thoughts?
2 months ago
If you're interested, check out my final (maybe) solution code for Day 7: https://github.com/jlacar/aoc-2023-kotlin/blob/main/src/Day07.kt

I think that's about as tight as I can get my Kotlin at this point, but if you think there's another notch please let me know.
2 months ago

Les Morgan wrote:Rashad,
besides the excellent advice that has already been given, consider this: when i was doing my English undergraduate work, my English instructor told us: "Writers write.  Everyday."  

as a programmer, the more you design and code, the better it will become.  i am at the far end of my career, and i look at some of the "really good code" from early in my career, and i am ashamed to let anyone see it, but some of those projects are still in production and running perfectly almost 3 decades later.

Being afraid that you'll do something that sucks or makes you look stupid is one of the biggest impediments to learning. Get over it. Put yourself out there. Get feedback and advice. Look at how other people do it and if you think it's better than your way, try to replicate it.

I've been working on Advent of Code puzzles and certainly some of my solutions suck. They're too long, too complicated, and inelegant. I'm ok with that. I don't care about anyone thinking that I'm stupid because I know I'm not. Not caring about what other people might say or think about me frees me up to do stupid things. When I do stupid things, I can learn. The more I learn, the less I do stupid things (hopefully).

in any case, take the direction given to me about writers: "writers write.  everyday."

This is the way. If you do something every day and learn a little bit each time, getting good at that thing is practically guaranteed.

Remember: Practice makes permanent. Only perfect practice makes perfect. Be mindful of what you're doing and how you're doing it. Learn to recognize mistakes and opportunities to improve. Don't just go through the motions; practice deliberately, with clear intent.

2 months ago

Junilu Lacar wrote:
You could even get rid of the "seed" explaining variable but I prefer to keep it.

I take it back. Should have tried it before posting. When I did this, the performance took a significant hit. I guess Kotlin is calling convert() multiple times when it evaluates the any() part. To keep the performance, you have to use that temporary seed variable so it's only executed once per iteration of the generated sequence. I profiled it again and this time part 2 took only 5,093ms to complete 20million iterations.
2 months ago
Well, one thing's for sure, I still have a ways to go to be truly conversant with Kotlin. I've been following this guy named Todd Ginsberg and I find his Kotlin solutions simply amazing in their elegance. For example, I (finally) completed Day 5 Part 2 yesterday but it was taking several minutes (6 to 8 mins) to complete its run. I did not know how to make it perform better.  I looked at Todd's solution and was skeptical that his approach would perform well but when I tried it, it took 6.4 seconds (I ran with a profiler) to complete over 20 million iterations. I know the exact number of iterations because it was also the answer to my puzzle.

His approach was quite simple but something that just escaped me, I wouldn't have thought to do it this way. Basically, he started with the end value (the location) and just went through all possible values until he found one that converted to a seed value that was in any of the ranges given in the puzzle input.

The Kotlin code pretty much says that.

You could even get rid of the "seed" explaining variable but I prefer to keep it.

Just mwah! (chef kiss)
2 months ago

Stephan van Hulst wrote:
Looks similar to what I had:

That's awesome. Like minds...  
2 months ago
Still working through Day 5 part 1 (already the 9th day of Advent!!!). Hoping I can catch up a little bit this weekend.

Can't say enough about declarative style coding. I find it very helpful and fun to back into the solution by declaring the code I want to write. Here's what I declared for Day 5, part 1:

Edit #1: Ah! Found a bug already just by looking at that code. Off by one:

Edit #2: And as I keep working the problem, I'm also changing the way the code tells the story:
2 months ago
4. Using .also scope function for inline debugging statements

If I format them right, I can use IDEA's rectangular (column-wise) selection feature to easily add debugging statements:

When I don't need them, I just rectangular highlight the .also parts and delete or comment them out.

Just did this for Day 4 Part 2, which I just got done solving.

Who needs sleep when you can code in Kotlin all night!  
2 months ago
Having lots of fun re-upping my Kotlin skills with this year's AoC.

Here are some things I've done that I think are shareable.

1. Testing without JUnit - I'm trying to avoid using JUnit and just testing with check(), like so:

I just discovered the check() has a lazyMessage parameter, which is nice. At some point I might cave and start using JUnit but doing this still helps me do TDD well enough.

2. Declarative/functional programming is nice!

I'm starting to settle on a problem-solving approach that's kind of "bass ackwards" but very much in line with TDD philosophy: Start with the end in mind. I'm working on Day 4 Part 2 right now and here's what I started writing:

That's it. To get the answer, I work my way backwards and implement each of these steps, breaking each one down into smaller problems when necessary.

3. Kotlin makes it easy to create DSLs (Domain Specific Languages)

Extension functions really help for declarative/functional programming. Here's what the asCards() function ended up being:

and ScratchCard is a data class with the of() factory function/method as a part of its companion object. This does the heavy lifting of parsing the input.

There are a few more things I'm playing around with but this is getting long and I have to get back to solving Day 4 Part 2. I'm falling way behind with all the reflection and playing around that I'm doing, but it's fun.
2 months ago