Pythonically restricting attribute access using properties - coding-style

I'm trying to write a short class to represent an object stored on a remote server. I expect setting attributes of the object locally without setting them on the remote server will generally be a bad idea; it'll mean the local object no longer represents the remote one, without even being aware of that fact.
I had planned on using code like the below to handle this. It lets you shoot yourself in the foot if you want to set item.name, but assumes users will be sensible and not do so.
class Item(object):
def __init__(self):
self.name = get_item_name()
def set_name(self, name):
try:
set_item_name(name)
except:
handle_error()
raise
else:
self.name = name
However, I recently came across the #property decorator, which let me write the below:
class Item(object):
def __init__(self):
self._name = get_item_name()
#property
def name(self):
return self._name
#name.setter
def name(self, value):
try:
set_item_name(value)
except:
handle_error()
raise
else:
self._name = value
This has the advantage of still allowing attribute access using item.name, but also handling item.name = blah assignment.
However, while the second block of code offers (what seems to me to be) nicer behaviour, it hides a function call in attribute setting, and given the Zen's "Explicit is better than implicit" and the general idea that Python classes should not hide things from their users, does this make the second block of code less Pythonic?

Writing code in OO languages is all about hiding things. When you write a method doSomethingComplex(), you basically create a new word in the language of your application which hides some complex operation from the developer who has to use the method.
While explicit is usually better than implicit that doesn't mean always. In your case, the problem is not in hiding the method call in the setter but in the fact that you're hiding the network. As soon as you try to hide the real, physical network from the user of a method, you need to make sure you handle the following cases correctly:
The remote side suddenly dies
The network drops packets (timeout on local side)
The remote side throws an exception (you must somehow get it to the local code but it might be meaningless locally)
The remote side successfully processes the call but the network drops the answer (so you did succeed but you don't know)
No matter how hard you try, this hidden complexity will leak through. As a simple example, developers using this code will have to handle network exceptions and timeouts (as opposed to any other method).
So the break here is less that you call a method in a setter but that you introduce a completely new contract.
What is a better solution? Make the network call explicit. That means more obvious effort for users of the code but they will always know what they're up against (instead of wondering why this setter behaves so oddly).
Suggested implementation: Use the command pattern to modify the state of these objects. The command needs the ID of the object to modify (so you don't have to keep a local copy), the field to change and the new value.
Update the local cached copy when the remote side replies "success". If the remote side returns an error, drop the cached copy so it gets fetched again.
This will create a lot more code but this code will be pretty simple and obvious. When you try to hide the remote side, you will have less code but it will be more complex and obscure.
PS: Never assume that people are sensible over an extended period of time.

Related

Subclassing commands.Bot vs instantiating it

I usually see this in code:
class MyBotClient(commands.Bot):
async def on_ready()....
client = MyBotClient()
But I always do this in my code:
client = commands.Bot(command_prefix=....)
What is the difference between these two methods, and is there any advantage of either of them?
Customizability, Maintainability and Code Cleanliness
The difference is mainly customizability, maintainability and code cleanliness.
Code Cleanliness
I had like 10 variables that are an attribute of client, e.g.
bot = commands.Bot(...)
bot.x = ""
bot.y = 1
bot.z = 0.2
# and so on to like 10 lines...
when I created my own class, I put it in another file and the class is like
class MyBot(commands.Bot):
def __init__(self, *args, **kwargs):
self.x = ""
self.y = 1
self.z = 0.2
# and so on...
Now my main file just cleanly creates the bot and runs it, simple, but this is mainly because it's open-source
Customizability
Subclassing allows you to extend, expand, and even diminish, or
degrade, the existing functions and coroutines. Perhaps to add extra
validation of parameters, perform additional processing to the
original function, or even to change the purpose of the function or
coroutine altogether.
From What Are the Benefits of Subclassing (Visual Basic)
You can add/change so much with a subclassed bot, for example, you can make a custom context class that is returned instead of the usual commands.Context, this would allow you to add custom functions/attributes to even the context. One of the things I did is that I overrode the send method of my custom context so that it replies to the user on every command
Maintainability
This kinda falls under code cleanliness as it makes the code easier to maintain/change in the future. Like all your events can stay in one place, and even in my example before, I had like 140 commands at the time, I wanted the bot to switch to the new discord reply system, I didn't need to replace ctx.send with ctx.reply everywhere in each file, I just overrode the send to use reply unless it's explicitly disallowed

How to check whether an instance of an ActiveRecord model is up to date?

For testing reasons, I want to check that one of my methods doesn't update a specific entry in my database. Is there a simple way to ask an instance of an ActiveRecord model if its in sync with the database? for instance, if we had a method foobar? that could do this:
old_post = Post.find(1)
updated_post = Post.find(1)
updated_post.update_attributes(name: "this is a new name not like the old name")
old_post.foobar? #should return true, as its attributes are no longer up to date
updated_post.foobar? #should return false, as its attributes match the database directly
So is there a method that acts like foobar, or something like it? Thanks in advance.
I think your problem lies beyond finding a method which tells you wether an attribute has been updated, but in the relationship among the different objects that are instantiated. First it is important to understand, that old_post and updated_post are unrelated ruby objects. They know about how to save their own state to the database, but they do not know about each other.
Therefore your first requirement for foobar? cannot be fulfilled, as old_post will think it is up-to-date as long as no attribute has been updated. In contrast the changed? method will roughly answer in the way you are trying to achieve for updated_post. However it does so because it thinks nothing has happened since it was last saved, this will not be verified against the database upon each call of changed? as this would be wasting a database call in 99.9% of all cases.
This means it is all too easy to generate anomalies between the objects you created as there is no direct connection between the two (except the implicit connection that they once represented the same database row). If you change an attribute in one object (using e.g. title='?' it will change the value of the object and take note of the change in the changed-array. Once you save this object it will save its changed attributes to the database (by creating an individually constructed update-statement).
Another object that is already instantiated (as old_post in your example) will not know about this change and might change other attributes if you are not careful (or even the same ones if they have been changed again). Depending on your database adapter you may try to use the lock! method which will synchronize your object with the database before allowing any modifications. This however will not happen automatically as in most controller methods updates do not conflict nearly often enough to merit the synchronization as it will be idempotent in most cases.
This does not go without saying that rails can not save you from thinking about your transaction semantics if you want to guarantee specific ACID semantics for your controller methods.

Ruby: slow down evaluation

I'm interested in simply slowing down the evaluation of ruby code. Of course I know about using sleep(), but that does not solve my problem.
Rather, I want to slow down every single object instantiation and destruction that happens in the VM.
Why? So I can learn about how particular procedures in ruby work by watching them being carried out. I recently learned about ObjectSpace and the ability to see/inspect all the objects currently living in a Ruby VM. It seems that building a simple realtime display of the objects and properties of those objects within the ObjectSpace and then slowing down the evaluation would achieve this.
I realize there may be ways of viewing in realtime more detailed logs of what is happening inside the ruby process, including many procedures that are implemented at low-level, below the level of actual ruby code. But I think simply seeing the creation and destruction of objects and their properties in realtime would be more edifying and easier to follow.
You could be interested in the answer to this question: getting in-out from ruby methods
With small edits to the code reported there, you could add a sleep to each method call and follow the code execution.
If you want to output some information every time an object is instantiated, you could do that by overriding Class#new. Here's an example:
class Class
alias old_new new
def new(*args)
puts "Creating: #{self.inspect}"
sleep 0.1
old_new(*args)
end
end
class Point
end
class Circle
end
The alias old_new new line creates a backup new method, so we can have the old behaviour. Then, we override the new method and put some code to inspect the subject class and sleep for just a bit for the sake of better readability. Now, if you invoke Point.new, you'll see "Creating: Point". Circle.new will display a "Creating: Circle" and so on. Any objects that are created will be logged, or at least their classes, with a small delay.
The example is a modified version of the one from here.
As for destruction of objects, I'm not sure if there's a sensible way to do it. You could try to override some method in the GC module, but garbage collection is only initiated when it's necessary (as far as I'm aware), so you could easily play with ruby for a while without it ever happening. It probably wouldn't be very useful anyway.
I think the problem is not that ruby is too fast.
In your case you should use some software architecture, for example Model-View-Controller.
It could be in this way. In View you can show options at which speed the Controller should show information for you or you're able to slow down or increase the speed of showing information. Then Controller evaluate small steps (calling methods in Model) and rendered the results of evaluation in the View.
The View is not always the browser or window application, it could be also just a simple terminal.

Ruby, Candy and SQL-like mongo stuff

So Candy is a really simple library for interacting with Mongo in Ruby.
My poor SQL brain is having a tough time figuring out how I should map out this problem:
There are users, there are things. Each thing was made by one user, but should be accessible to a subset of all users (specified within the thing). Leaving the specification of user out of the way for now, how would I get a list of all things that user X has access to?
class Thing
include Candy::Piece
end
class Things
include Candy::Collection
collects :thing
end
Should I assign the allowed users to a thing like this? (lets just use strings to reference users for now)
t = Thing.new
t.allowed = ['X','Y','Z']
This seems about right to me, which would make me want to do:
Things.find(allowed:'X')
but it's not quite working…
NoMethodError: undefined method ‘call’ for {:allowed=>"X"}:Hash
any ideas?
I'm really sorry I took so long to catch this and respond. This might be too late for your purposes, but:
Candy doesn't implement a find method. This is on purpose: if an object represents a collection, every access is implicitly finding something in that collection. It's the same reason there is no save method. If the mapping is truly transparent, verbs that mean "Do this in the database" shouldn't be necessary.
So to do what you want, you could either just make a new Things object with the scope passed on creation:
x_is_allowed = Things.new(allowed: 'X')
...or you could save a step and do it by class method:
x_is_allowed = Things.allowed('X')
...or you could start with the whole collection and limit it by attribute later:
things = Things.new
x_is_allowed = things.allowed('X')
So... Um. All of those will work. But. I have to warn you that I'm really not happy with the general usability of Candy right now, and of collections and array fields in particular. The biggest problem is accessors: the [] method isn't working like you'd expect, so you end up having to call to_a and refresh and other things that feel sticky and unpleasant.
This needs to be fixed, and I will do so as soon as I finish the driver rewrite (a related project called Crunch). In the short term, Candy is probably best viewed as an experiment for the adventurous, and I can't guarantee it'll save time until the interface is locked down a bit better. I'm sorry about that.

OO Design: Multiple persistance design for a ruby class

I am designing a class for log entries of my mail server. I have parsed the log entries and created the class hierarchy. Now I need to save the in memory representation to the disk. I need to save it to multiple destinations like mysql and disk files. I am at a loss to find out the proper way to design the persistence mechanism. The challenges are:
How to pass persistence
initialization information like
filename, db connection parameters
passed to them. The options I can
think of are all ugly for eg:
1.1 Constructor: it becomes ugly as I
add more persistence.
1.2 Method: Object.mysql_params(" "),
again butt ugly
"Correct" method name to call each
persistance mechanism: eg:
Object.save_mysql, Object.save_file,
or Object.save (mysql) and
Object.save(file)
I am sure there is some pattern to solve this particular problem. I am using ruby as my language, with out any rails, ie pure ruby code. Any clue is much welcome.
raj
Personally I'd break things out a bit - the object representing a log entry really shouldn't be worrying about how it should save it, so I'd probably create a MySQLObjectStore, and FileObjectStore, which you can configure separately, and gets passed the object to save. You could give your Object class a class variable which contains the store type, to be called on save.
class Object
cattr_accessor :store
def save
##store.save(self)
end
end
class MySQLObjectStore
def initialize(connection_string)
# Connect to DB etc...
end
def save(obj)
# Write to database
end
end
store = MySQLObjectStore.new("user:password#localhost/database")
Object.store = store
obj = Object.new(foo)
obj.save
Unless I completely misunstood your question, I would recommend using the Strategy pattern. Instead of having this one class try to write to all of those different sources, delegate that responsibility to another class. Have a bunch of LogWriter classes, each one with the responsibility of persiting the object to a particular data store. So you might have a MySqlLogWriter, FileLogWriter, etc.
Each one of these objects can be instantiated on their own and then the persitence object can be passed to it:
lw = FileLogWriter.new "log_file.txt"
lw.Write(log)
You really should separate your concerns here. The message and the way the message is saved are two separate things. In fact, in many cases, it would also be more efficient not to open a new mysql connection or new file pointer for every message.
I would create a Saver class, extended by FileSaver and MysqlSaver, each of which have a save method, which is passed your message. The saver is responsible for pulling out the parts of the message that apply and saving them to the medium it's responsible for.

Resources